1
0
Fork 0
Godot Engine – Multi-platform 2D and 3D game engine
Go to file
Matias N. Goldberg c77cbf096b Improvements from TheForge (see description)
The work was performed by collaboration of TheForge and Google. I am
merely splitting it up into smaller PRs and cleaning it up.

This is the most "risky" PR so far because the previous ones have been
miscellaneous stuff aimed at either [improve
debugging](https://github.com/godotengine/godot/pull/90993) (e.g. device
lost), [improve Android
experience](https://github.com/godotengine/godot/pull/96439) (add Swappy
for better Frame Pacing + Pre-Transformed Swapchains for slightly better
performance), or harmless [ASTC
improvements](https://github.com/godotengine/godot/pull/96045) (better
performance by simply toggling a feature when available).

However this PR contains larger modifications aimed at improving
performance or reducing memory fragmentation. With greater
modifications, come greater risks of bugs or breakage.

Changes introduced by this PR:

TBDR GPUs (e.g. most of Android + iOS + M1 Apple) support rendering to
Render Targets that are not backed by actual GPU memory (everything
stays in cache). This works as long as load action isn't `LOAD`, and
store action must be `DONT_CARE`. This saves VRAM (it also makes
painfully obvious when a mistake introduces a performance regression).
Of particular usefulness is when doing MSAA and keeping the raw MSAA
content is not necessary.

Some GPUs get faster when the sampler settings are hard-coded into the
GLSL shaders (instead of being dynamically bound at runtime). This
required changes to the GLSL shaders, PSO creation routines, Descriptor
creation routines, and Descriptor binding routines.

 - `bool immutable_samplers_enabled = true`

Setting it to false enforces the old behavior. Useful for debugging bugs
and regressions.

Immutable samplers requires that the samplers stay... immutable, hence
this boolean is useful if the promise gets broken. We might want to turn
this into a `GLOBAL_DEF` setting.

Instead of creating dozen/hundreds/thousands of `VkDescriptorSet` every
frame that need to be freed individually when they are no longer needed,
they all get freed at once by resetting the whole pool. Once the whole
pool is no longer in use by the GPU, it gets reset and its memory
recycled. Descriptor sets that are created to be kept around for longer
or forever (i.e. not created and freed within the same frame) **must
not** use linear pools. There may be more than one pool per frame. How
many pools per frame Godot ends up with depends on its capacity, and
that is controlled by
`rendering/rendering_device/vulkan/max_descriptors_per_pool`.

- **Possible improvement for later:** It should be possible for Godot
to adapt to how many descriptors per pool are needed on a per-key basis
(i.e. grow their capacity like `std::vector` does) after rendering a few
frames; which would be better than the current solution of having a
single global value for all pools (`max_descriptors_per_pool`) that the
user needs to tweak.

 - `bool linear_descriptor_pools_enabled = true`

Setting it to false enforces the old behavior. Useful for debugging bugs
and regressions.
Setting it to false is required when workarounding driver bugs (e.g.
Adreno 730).

A ridiculous optimization. Ridiculous because the original code
should've done this in the first place. Previously Godot was doing the
following:

  1. Create a command buffer **pool**. One per frame.
  2. Create multiple command buffers from the pool in point 1.
3. Call `vkBeginCommandBuffer` on the cmd buffer in point 2. This
resets the cmd buffer because Godot requests the
`VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT` flag.
  4. Add commands to the cmd buffers from point 2.
  5. Submit those commands.
6. On frame N + 2, recycle the buffer pool and cmd buffers from pt 1 &
2, and repeat from step 3.

The problem here is that step 3 resets each command buffer individually.
Initially Godot used to have 1 cmd buffer per pool, thus the impact is
very low.

But not anymore (specially with Adreno workarounds to force splitting
compute dispatches into a new cmd buffer, more on this later). However
Godot keeps around a very low amount of command buffers per frame.

The recommended method is to reset the whole pool, to reset all cmd
buffers at once. Hence the new steps would be:

  1. Create a command buffer **pool**. One per frame.
  2. Create multiple command buffers from the pool in point 1.
3. Call `vkBeginCommandBuffer` on the cmd buffer in point 2, which is
already reset/empty (see step 6).
  4. Add commands to the cmd buffers from point 2.
  5. Submit those commands.
6. On frame N + 2, recycle the buffer pool and cmd buffers from pt 1 &
2, call `vkResetCommandPool` and repeat from step 3.

**Possible issues:** @dariosamo added `transfer_worker` which creates a
command buffer pool:

```cpp
transfer_worker->command_pool =
driver->command_pool_create(transfer_queue_family,
RDD::COMMAND_BUFFER_TYPE_PRIMARY);
```

As expected, validation was complaining that command buffers were being
reused without being reset (that's good, we now know Validation Layers
will warn us of wrong use).
I fixed it by adding:

```cpp
void RenderingDevice::_wait_for_transfer_worker(TransferWorker
*p_transfer_worker) {
	driver->fence_wait(p_transfer_worker->command_fence);
	driver->command_pool_reset(p_transfer_worker->command_pool); //
! New line !
```

**Secondary cmd buffers are subject to the same issue but I didn't alter
them. I talked this with Dario and he is aware of this.**
Secondary cmd buffers are currently disabled due to other issues (it's
disabled on master).

 - `bool RenderingDeviceCommons::command_pool_reset_enabled`

Setting it to false enforces the old behavior. Useful for debugging bugs
and regressions.

There's no other reason for this boolean. Possibly once it becomes well
tested, the boolean could be removed entirely.

Adds `command_bind_render_uniform_sets` and
`add_draw_list_bind_uniform_sets` (+ compute variants).

It performs the same as `add_draw_list_bind_uniform_set` (notice
singular vs plural), but on multiple consecutive uniform sets, thus
reducing graph and draw call overhead.

 - `bool descriptor_set_batching = true;`

Setting it to false enforces the old behavior. Useful for debugging bugs
and regressions.

There's no other reason for this boolean. Possibly once it becomes well
tested, the boolean could be removed entirely.

Godot currently does the following:

 1. Fill the entire cmd buffer with commands.
 2. `submit()`
    - Wait with a semaphore for the swapchain.
- Trigger a semaphore to indicate when we're done (so the swapchain
can submit).
 3. `present()`

The optimization opportunity here is that 95% of Godot's rendering is
done offscreen.
Then a fullscreen pass copies everything to the swapchain. Godot doesn't
practically render directly to the swapchain.

The problem with this is that the GPU has to wait for the swapchain to
be released **to start anything**, when we could start *much earlier*.
Only the final blit pass must wait for the swapchain.

TheForge changed it to the following (more complicated, I'm simplifying
the idea):

 1. Fill the entire cmd buffer with commands.
 2. In `screen_prepare_for_drawing` do `submit()`
    - There are no semaphore waits for the swapchain.
    - Trigger a semaphore to indicate when we're done.
3. Fill a new cmd buffer that only does the final blit to the
swapchain.
 4. `submit()`
    - Wait with a semaphore for the submit() from step 2.
- Wait with a semaphore for the swapchain (so the swapchain can
submit).
- Trigger a semaphore to indicate when we're done (so the swapchain
can submit).
 5. `present()`

Dario discovered this problem independently while working on a different
platform.

**However TheForge's solution had to be rewritten from scratch:** The
complexity to achieve the solution was high and quite difficult to
maintain with the way Godot works now (after Übershaders PR).
But on the other hand, re-implementing the solution became much simpler
because Dario already had to do something similar: To fix an Adreno 730
driver bug, he had to implement splitting command buffers. **This is
exactly what we need!**. Thus it was re-written using this existing
functionality for a new purpose.

To achieve this, I added a new argument, `bool p_split_cmd_buffer`, to
`RenderingDeviceGraph::add_draw_list_begin`, which is only set to true
by `RenderingDevice::draw_list_begin_for_screen`.

The graph will split the draw list into its own command buffer.

 - `bool split_swapchain_into_its_own_cmd_buffer = true;`

Setting it to false enforces the old behavior. This might be necessary
for consoles which follow an alternate solution to the same problem.
If not, then we should consider removing it.

PR #90993 added `shader_destroy_modules()` but it was not actually in
use.

This PR adds several places where `shader_destroy_modules()` is called
after initialization to free up memory of SPIR-V structures that are no
longer needed.
2024-12-09 11:49:28 -03:00
.github CI: Add explicit problem matchers 2024-11-27 16:47:34 -06:00
core Merge pull request #99817 from Ivorforce/strlen-char32_t 2024-12-05 14:12:21 -06:00
doc Improvements from TheForge (see description) 2024-12-09 11:49:28 -03:00
drivers Improvements from TheForge (see description) 2024-12-09 11:49:28 -03:00
editor Merge pull request #99947 from Meorge/ignore-macosx-in-zip 2024-12-05 14:12:22 -06:00
main Merge pull request #98383 from RandomShaper/deprecate_unsafe_th_rend 2024-12-03 14:40:56 -06:00
misc Merge pull request #99051 from bruvzg/ios_entitlements 2024-12-02 17:20:11 +01:00
modules Merge pull request #99327 from colinator27/sync-bar-beats 2024-12-05 14:12:26 -06:00
platform Merge pull request #100047 from MBCX/fix-freebsd-compilation 2024-12-05 14:12:11 -06:00
scene Merge pull request #96735 from bruvzg/rtl_frame_indent 2024-12-05 14:12:18 -06:00
servers Improvements from TheForge (see description) 2024-12-09 11:49:28 -03:00
tests Merge pull request #99960 from pafuent/fixing_tcp_server_flappy_disconnect_test 2024-12-06 16:16:17 +01:00
thirdparty Improvements from TheForge (see description) 2024-12-09 11:49:28 -03:00
.clang-format Style: Downgrade `.clang-format` arguments to 17.x 2024-11-27 10:11:17 -06:00
.clang-tidy Style: Apply `clang-tidy` fixes 2024-11-04 12:11:06 -06:00
.editorconfig CI: Add `svgo` pre-commit hook 2024-06-23 08:14:54 -05:00
.git-blame-ignore-revs clang-tidy commit to `.git-blame-ignore-revs` 2024-11-04 12:11:39 -06:00
.gitattributes Correct C++ highlighting settings in .gitattributes 2024-08-27 23:24:30 +02:00
.gitignore Merge pull request #98093 from zynga-jpetersen/jpetersen/ios_xcode_PROVISIONING_PROFILE_SPECIFIER_support 2024-11-29 22:46:29 +01:00
.mailmap Update AUTHORS and DONORS list 2024-09-17 13:07:39 +02:00
.pre-commit-config.yaml Merge pull request #99490 from dalexeev/gds-tests-track-multiple-errors 2024-11-29 22:02:02 +01:00
AUTHORS.md Update AUTHORS and DONORS list 2024-09-17 13:07:39 +02:00
CHANGELOG.md Add changelog for Godot 4.3 2024-08-15 00:57:57 +02:00
CONTRIBUTING.md Update godot documentation contribution link 2024-07-20 20:51:11 -06:00
COPYRIGHT.txt Change default Arabic font to Vazirmatn. 2024-12-05 16:26:52 +02:00
DONORS.md Update AUTHORS and DONORS list 2024-09-17 13:07:39 +02:00
LICENSE.txt One Copyright Update to rule them all 2023-01-05 13:25:55 +01:00
LOGO_LICENSE.txt Cleanup various repository documentation files 2023-10-10 13:58:13 +02:00
README.md Cleanup various repository documentation files 2023-10-10 13:58:13 +02:00
SConstruct Merge pull request #99351 from dustdfg/scons_android_refactor 2024-11-21 17:56:59 -06:00
gles3_builders.py SCons: Add method to generate raw cstrings 2024-07-31 14:22:04 -05:00
glsl_builders.py SCons: Add method to generate raw cstrings 2024-07-31 14:22:04 -05:00
godot.manifest [Windows] Always use absolute UNC paths and long path aware APIs, add "long path aware" flag to the application manifest. 2024-08-28 11:15:57 +03:00
icon.png
icon.svg Style: Optimize `.svg` files with `svgo` 2024-06-23 08:15:19 -05:00
icon_outlined.png
icon_outlined.svg Style: Optimize `.svg` files with `svgo` 2024-06-23 08:15:19 -05:00
logo.png
logo.svg Style: Optimize `.svg` files with `svgo` 2024-06-23 08:15:19 -05:00
logo_outlined.png Convert the logo's text outlines into paths 2023-04-07 17:51:56 +02:00
logo_outlined.svg Style: Optimize `.svg` files with `svgo` 2024-06-23 08:15:19 -05:00
methods.py [Buildsystem] Fix path format for SCU builds on Windows 2024-11-24 15:33:47 +01:00
platform_methods.py Add loongarch64 support 2024-12-06 00:18:26 +08:00
pyproject.toml Style: Update `pyproject.toml` syntax 2024-11-14 13:05:21 -06:00
scu_builders.py Make SCons SCU build banner less intrusive 2024-11-08 13:46:26 +01:00
version.py Bump version to 4.4-dev 2024-08-15 11:39:34 +02:00

README.md

Godot Engine

Godot Engine logo

2D and 3D cross-platform game engine

Godot Engine is a feature-packed, cross-platform game engine to create 2D and 3D games from a unified interface. It provides a comprehensive set of common tools, so that users can focus on making games without having to reinvent the wheel. Games can be exported with one click to a number of platforms, including the major desktop platforms (Linux, macOS, Windows), mobile platforms (Android, iOS), as well as Web-based platforms and consoles.

Free, open source and community-driven

Godot is completely free and open source under the very permissive MIT license. No strings attached, no royalties, nothing. The users' games are theirs, down to the last line of engine code. Godot's development is fully independent and community-driven, empowering users to help shape their engine to match their expectations. It is supported by the Godot Foundation not-for-profit.

Before being open sourced in February 2014, Godot had been developed by Juan Linietsky and Ariel Manzur (both still maintaining the project) for several years as an in-house engine, used to publish several work-for-hire titles.

Screenshot of a 3D scene in the Godot Engine editor

Getting the engine

Binary downloads

Official binaries for the Godot editor and the export templates can be found on the Godot website.

Compiling from source

See the official docs for compilation instructions for every supported platform.

Community and contributing

Godot is not only an engine but an ever-growing community of users and engine developers. The main community channels are listed on the homepage.

The best way to get in touch with the core engine developers is to join the Godot Contributors Chat.

To get started contributing to the project, see the contributing guide. This document also includes guidelines for reporting bugs.

Documentation and demos

The official documentation is hosted on Read the Docs. It is maintained by the Godot community in its own GitHub repository.

The class reference is also accessible from the Godot editor.

We also maintain official demos in their own GitHub repository as well as a list of awesome Godot community resources.

There are also a number of other learning resources provided by the community, such as text and video tutorials, demos, etc. Consult the community channels for more information.

Code Triagers Badge Translate on Weblate TODOs