GLES2 2d Batch rendering (across items)

2d rendering is currently bottlenecked by drawing primitives one at a time, limiting OpenGL efficiency. This PR batches primitives and renders in fewer drawcalls, resulting in significant performance improvements. This also speeds up text rendering.
This PR batches across canvas items as well as within items.
The code dynamically chooses between a vertex format with and without color, depending on the input data for a frame, in order to optimize throughput and maximize batch size.
Test Builds
Many thanks to Akien for making test builds (more info further down thread), please try them out and let us know how you get on with your game / test projects. Let us know especially any visual bugs so we can fix them! :+1:
https://downloads.tuxfamily.org/godotengine/testing/3.2.2-gles2_batching_build2/
Notes

This is an enhanced version of my original PR #35957, which could not batch across multiple items
This currently batches only rects
The batching settings are in projectsettings/rendering/gles2/ and the new rendering can be toggled with the old behaviour using the use_batching boolean
There is an experimental option use_batching_in_editor. Only use this when you are sure it is working fine for some of your projects. This is more for finding regressions at this point than for editor performance.

History and Explanation
I rewrote the 2d renderer several times (this is probably the 4th or so version, and about the 7th iteration). An earlier version was in fact considerably more advanced, however a massive problem in practice has been regressions between the new renderer behaviour and the old renderer. To that end I threw out a lot of earlier work and considerably simplified the problem in order to retain as much of the existing logic as possible and maintain compatibility.
In the original PR it proved simple enough to batch commands within a render item. This worked for many cases such as tilemaps and text. However there was keenness to be able to batch different items together where possible, such as in bunnymark, with large numbers of independently moving sprites.

The simple approach taken here was to add an extra pass to the items, to identify any that could be joined with the previous item, to form joined_items. This entails duplicating a simplified version of the state logic.
The next stage was to modify the existing renderer to deal with joined_items rather than single items.
Finally the existing code in the old PR was used to batch the commands in these joined items.

An important consideration was the functions had to be able to be called multiple times instead of a single time, because it had to deal with the situation where the vertex buffer was full, flush, then refill.
In addition in order to batch between items, where items are joined, it is necessary to use software transform. However, where items cannot be joined, or the items contain a large number of commands, the items are not joined and hardware transform is used. This retains maximum speed for tilemaps and large areas of text.
Future
We can add batching for other primitives using the same method. Note that this PR is made against Godot 3.2 but is also designed to eventually be used in 4.0.
Performance increases - what to expect
Most importantly, the frame rate increases you will get will be highly dependent on what are the bottlenecks in your game. It MAY NOT speed up all games, especially those that are running fast already - some will see great differences, others, not so much.

Generally, the more rects you have on screen, the higher the density of your tilemaps, the more text, the more you are likely to benefit.
If you are only drawing a small number of rects you are unlikely to be bottlenecked by drawcalls, and will see less benefit.
If you are bottlenecked by fillrate (e.g. a smaller screen results in higher frame rate) you will see less benefit.
You will typically see relative larger performance increase in release builds than in debug builds, because the batching is CPU limited.

The performance increases should be on a par with the old PR, with the addition of increases due to batching across items.
However, I will say that the additional benefits of the batching across items versus just batching within items may not be that huge in real world use cases, versus test cases, as it is less likely to be a bottleneck.
How bottlenecks work
If the game is spending 1% of the time making drawcalls, even if we speed up the batching 100%, you only have 1% of gain available. If on the other hand your game is spending 80% of time in drawcalls, you can see very large performance increases. You can either use profiling to examine this (a large amount of time spent in the graphics driver normally indicates API bottlenecks), or simple try out the build.
A Quick Guide
The settings are in ProjectSettings->Rendering->Gles2

use_batching - turns on and off (you can easily compare frame rates with and without)
flash_batching - if batching is on, this alternates between the legacy renderer and batching on alternate frames - this can help find visual differences, which you should report here so I can fix
use_batching_in_editor - this will restart the editor and use batching to render the Godot IDE. Providing running projects look ok with batching, I'm 99.9% sure running in the editor should be fine too. Please report any visual differences in behaviour in the editor so I can fix.
max_join_item_commands - the default should work fine, but it is possible that different values may give you slightly better results in your game. A value of 0 turns joining items off, which can be used to help diagnose regressions (it will usually slightly decrease batching gains though).
colored_vertex_format_threshold - try varying this to see how it affects the performance in your game, the best value may be game / hardware dependent, we are not sure yet.
light_scissor_area_threshold - if you are using lights in your game, be sure to test varying this, even if you do not benefit from batching. This can significantly reduce GPU fillrate requirements, which can be a bottleneck in some games.

Just starting taking a look now. Run it through my previous test project and I am still getting ~5x speedup (heavy text with interleaved sprites and lights). I will review the code this afternoon and we can discuss what to do next tomorrow.

heavy text with interleaved sprites

The lights is interesting and something I briefly discussed with reduz. You'll notice in the try_join_item logic there is a large commented section with light logic, and at the moment it simply breaks the between item batching when lights are used.
It shouldn't need to in theory, but in practice if there are overlaps between geometry, I found the result of joined items is different when lit, because of multiple passes:
i.e. (a * light) + (b * light) is NOT the same as (a + b) * light
Tilemaps etc do still benefit even with lights though. In fact there's another small optimization I haven't put in yet which should help on the lights front. Provided the vertex buffer isn't full, it can be reused for each light. At the moment it is refilled for the main pass and each light. The current method should still should be miles faster than the old method though.
There's quite a bit of low hanging fruit in general still available for optimization, and indeed adding other primitives, but I'd ideally prefer to get this more straightforward approach in use, to work out any regressions and get some feedback, before adding more, because the more code, the more difficult to debug. It's a bit of a balancing act really between run time speed and code complexity.
I forgot to mention in terms of review, I've moved a lot of the old code into RasterizerCanvasBase, and just left the higher level code and new stuff in RasterizerCanvas. As such you should be pretty much able to skim read over RasterizerCanvasBase as it is unchanged.

OMG, that was traumatic trying to test on Android. An entire day spent reinstalling android studio multiple times to get it to update so it would compile the latest version of the android templates. Then the old S3TC import bug on GLES2 #28308 (must get a fix for that merged) compounded by a new bug where Godot seems to keep trying to re-import textures because they aren't there, if you remove S3TC from the import list in ProjectSettings. :anguished:
Anyway upshot is that the PR seems to work fine for me both on the Android emulator and on my ancient Google Nexus 7 2013. :grin: Would appreciate more testing on devices / platforms though.
I suspect it will be ok everywhere because it doesn't do anything too funky API wise, and early ARM Android devices are the most likely to show up any problems because they will crash without properly aligned structures.

I can see how you left it open to extend this to other Command types fairly easily. I'm wondering if our best approach may be to make a "test-release" and link it in a blog post to get wider testing, even before merging the PR and then adding in some of the other command types in this PR. @akien-mga may have some thoughts on that. But I think that testing is necessary to making sure this works, and you've put in so much work so far, we really ought to get some wider testing before asking you to make the final leap and finish it up.

I think we should merge this in a dedicated branch (e.g. 3.2-gles2-batching), and I can use it to make official test builds to get wide testing before landing it in the stable branch.
If you agree, I can create that branch and we can just change the base branch for this PR on GitHub.

I think we should merge this in a dedicated branch (e.g. 3.2-gles2-batching), and I can use it to make official test builds to get wide testing before landing it in the stable branch.

I think this sounds like a good plan of action. There are a lot of 2d guys waiting for this so we should get quite a few testers and can fix any bugs.

Done, I changed the base branch to 3.2-gles2-batching.
I suggest we focus first on getting the current state merged, then I'll make a testing release, and we can work further on fixing regressions if there are any, and adding support for more primitives in subsequent PRs. WDYT?

Great! :+1:
Sounds good, I'll make the changes clayjohn has suggested, then it should be okay for some testing!

I have now added some more project settings, as requested. I figured out that I should be creating them in RasterizerCanvasGLES2 initialize, rather than in visual server, because they only apply to GLES2.
As there are now several settings instead of putting use_batching in the rendering/quality/2d section I added a section rendering/quality/2d_batching.
In that there are 3 settings:
use_batching
max_join_item_commands
colored_vertex_format_threshold
and to rendering/limits/buffers I have added 2d_batch_buffer_size.
I've given these all reasonable ranges. Let me know if there are any preferences for renaming these, or putting them in different places, this can easily be done. I've done some basic testing and they seem to work ok and are quite useful for diagnostics etc. We may decide to remove some in future.
I haven't yet written the class reference entries, will do that now, but committed first what I've added.
I've also added couple of lines to support zero buffer length in the rasterizer array, as it will use that if batching is turned off, to save memory, and fixed an un-initialized value for total_quads that was causing problems with one of these parameter settings (I've done fuller constructors for BatchData and RenderItemState).

I have now added some more project settings, as requested. I figured out that I should be creating them in RasterizerCanvasGLES2 initialize, rather than in visual server, because they only apply to GLES2.

I think you still have to define them in a common code branch, otherwise they will not be visible if using the editor with GLES3 (even if configured to use GLES2 on some platforms), and they won't appear in the docs unless we specifically generate docs with godot --video-driver GLES2 --doctool ..

I think you still have to define them in a common code branch, otherwise they will not be visible if using the editor with GLES3 (even if configured to use GLES2 on some platforms), and they won't appear in the docs unless we specifically generate docs with godot --video-driver GLES2 --doctool ..

Ah okay, I'll move them into visual_server.cpp. I only got that idea from searching in files for rendering/limits/buffers/canvas_polygon_buffer_size_kb and finding it was created in rasterizer_canvas_gles3.cpp, but maybe that is handled differently.

Ah okay, I'll move them into visual_server.cpp. I only got that idea from searching in files for rendering/limits/buffers/canvas_polygon_buffer_size_kb and finding it was created in rasterizer_canvas_gles3.cpp, but maybe that is handled differently.

Yeah that one seems to be defined both in rasterizer_canvas_gles2.cpp and rasterizer_canvas_gles3.cpp, so it works, though it's a bit inconsistent (it's also defined once with GLOBAL_DEF_RST and once with GLOBAL_DEF, so the behavior differs).
There's also rendering/quality/2d/gles2_use_nvidia_rect_flicker_workaround defined in main.cpp to be always defined even when using GLES3 (so that you don't miss it/lose the configured value when switching renderers).
It's all a bit brittle :)

Ok, I've moved the project/settings back to visual_server.cpp, and have added gles2_ to the corresponding names, and have added entries in the class reference. Seems to be working fine, let me know any other changes. :+1:
The max_join_commands setting is quite handy because if you set it to zero it will prevent joining items which will be useful for finding regressions.

@akien-mga Just a note that the CI has been repeatedly failing today (last 3 commits for this PR) on appveyor from timeouts (taking longer than 60 mins). I don't know if it is to do with the extra python checks that you were adding, or if it is just appveyor being slow. Maybe there isn't normal caching because we are on a new branch. I haven't changed any includes that might slow down, the only major change is adding to the ProjectSettings.xml class reference...
Anyway although there is a cross it doesn't indicate there's a problem with the code (well unless there was a problem that would have happened after timeout lol). :grin:

Hi! I'm trying test this feature beacuse it hypes me, i think in my game the bottlenecked is just this. But in the first tryed, i can't notice performance increases. I supossed what i had a lot of sprites, then a tryed in a empty scene, with only a TileMap (figure 1). but neither. I was testing the performance reading the fps with batch rendering, and without it
Any suggestions for see where is the bottlenecked?

@lawnjelly Yeah I guess it no longer uses the 3.2 cache due to the base branch change. And a build from scratch on AppVeyor takes... 57 to 65 min I guess? So it often times out. I'll change the base branch again for now and only change it back when merging.

@leamendoza97 With a single tilemap, it is unlikely that draw calls are a bottleneck for you. In which case, you shouldn't see any performance improvement.
We will be releases a testing build of 3.2 with this PR for broader public testing. Please wait until that is available before further testing. More instructions will be available then.

Hi! I'm trying test this feature beacuse it hypes me, i think in my game the bottlenecked is just this. But in the first tryed, i can't notice performance increases. I supossed what i had a lot of sprites, then a tryed in a empty scene, with only a TileMap (figure 1). but neither. I was testing the performance reading the fps with batch rendering, and without it
Any suggestions for see where is the bottlenecked?

You probably need to switch it on in the project settings. Look in rendering/quality/gles2_2d_batching and switch use_batching to on.
Maybe we should default it to on for this build?

I got bored and added another feature, based on fixing #23593. The issue reports performance problems due to fill rate because when drawing light passes, parts of items are unnecessarily drawn outside the light area.
I suggested 2 methods to solve this problem:

Clip primitives to the light area
Use glScissor to clip to the light area on the GPU

Light scissoring
I tested this morning and glScissor does work for this purpose and results in significant speedup for such situations, and has low cost. So I've added an extra project setting which enables this:
light_scissor_area_threshold, which is between 0.0 and 1.0.
Each light render pass it calculates the intersection area between the light and the item, and the area of the item. The area potentially saved by a scissoring operation is area_item - intersection_area.
The logic then applies, if the saved_area > some_threshold_area, it applies a glScissor.
The threshold area is calculated from the user setting as a proportion of screen area. The value of 1.0 corresponds to the entire screen area - the scissor would have to save the entire screen area to be activated. In practice this is used to turn scissoring off. It defaults to off.
A value of 0.0 means any area saved will activate scissoring, 0.5 is half the screen etc. The actual pixel area is calculated regularly in case the user resizes the screen.
I've added this in as it should be easy to test at the same time as the batching, but it could be easily separated as another PR. It could do with some testing on different hardware as I don't know yet whether scissor may be more expensive on some architectures (mobile / tiled renderers). On the other hand it could potentially be very useful on mobile because fill rate is so limited.
This is one of those features that may only be useful to 25% or so of game authors, but if you need it, you really need it. It also makes lights less expensive so will encourage more to use them.
Code changed
Very little was needed to add to get it working. There is the additional project setting, a call to _calculate_scissor_threshold_area at regular intervals to make sure the pixel area is correct in relation to screen size, then when rendering there is this small change which does the business:
				if (!bdata.settings_scissor_lights || r_ris.current_clip) {
					render_joined_item_commands(p_bij, NULL, reclip, material_ptr);
				} else {
					bool scissor = _light_scissor_begin(p_bij.bounding_rect, light->xform_cache, light->rect_cache);
					render_joined_item_commands(p_bij, NULL, reclip, material_ptr);
					if (scissor) {
						glDisable(GL_SCISSOR_TEST);
					}
				}

It will only scissor if a scissor is not already active (current_clip) because they could interfere.
The logic in _light_scissor_begin should be self explanatory.

Fixed regression where final_modulate wasn't being checked in try_join_item. Thanks to @Schroedi for finding the bug and minimum reproduction project in #35957.

Awesome that you work on this!
I noticed two bugs:
self_modulate on sprites does not work anymore with this PR
modulate effects all sprites in the scene.

Changes : Added new member final_modulate to RenderItemState and added it to the state checks in try_join_item.

I made a test build (3.2.2-gles2_batching_build1 from the current 3.2 branch (798bf901b8eaf63be28c0e7218564ee9034f16fe) + the current state of this PR (23cdac9b604d54ed4f0e77c524baf06cae8aa292):
https://downloads.tuxfamily.org/godotengine/testing/3.2.2-gles2_batching_build1/
(Note that it's still uploading, should be good within ~20 min.)

Hello, I’m a 2d guy who waited this PR!
Tested on small project with a lot of text and vsync off.
Desktop: Ubuntu 16.04.6 LTS, Nvidia 1060.
Batching Off: fps ≈ 1500
Batching On: fps ≈ 1900
Thank you so much for your hard work!

Yay!! Thanks Akien! :grinning:

Tested on small project with a lot of text and vsync off.
Desktop: Ubuntu 16.04.6 LTS, Nvidia 1060.
Batching Off: fps ≈ 1500
Batching On: fps ≈ 1900

Great! :+1: With high frame rates to start with you are probably not that limited by drawcalls, but you are still getting some benefit which is very good news. Try a test project that really taxes Godot with sprites / tilemap density, until you get a frame rate below 30fps, then enable batching. I will try and upload a couple of such test projects.
There is also a benefit to people who have already written games that already run at high FPS - there is now the option to add extra detail and effects.
A Quick Guide
The settings are mostly in ProjectSettings->Rendering->Quality->Gles2 2d Batching (there is one setting for buffer size in Rendering->Limits, but that should be fine to leave as is in most cases).

use_batching - turns on and off (you can easily compare frame rates with and without)
flash_batching - if batching is on, this alternates between the legacy renderer and batching on alternate frames - this can help find visual differences, which you should report here so I can fix
allow_in_editor - if batching is on, this will restart the editor and use batching to render the Godot IDE. Providing running projects look ok with batching, I'm 99.9% sure running in the editor should be fine too. Please report any visual differences in behaviour in the editor so I can fix.
max_join_item_commands - the default should work fine, but it is possible that different values may give you slightly better results in your game. A value of 0 turns joining items off, which can be used to help diagnose regressions (it will usually slightly decrease batching gains though).
colored_vertex_format_threshold - try varying this to see how it affects the performance in your game, the best value may be game / hardware dependent, we are not sure yet.
light_scissor_area_threshold - if you are using lights in your game, be sure to test varying this, even if you do not benefit from batching. This can significantly reduce GPU fillrate requirements, which can be a bottleneck in some games.

Test Benchmark Projects
Text Rendering
This is slightly modified version of @Geequlim 's minimum reproduction project in #19917
batch_test_text.zip
I clicked to add FIVE boxes of text. Compare results of frame rate with batching turned on and off (in ProjectSettings->Rendering->Quality->Gles2 2d Batching->Use_Batching).
On my Intel i5-7500T 2.7 ghz with Integrated HD Graphics 630, Linux Mint:

No Batching : 4fps
Batching : 328fps (82x speed increase)

Found a small visual bug that can occur with large numbers of batched sprites (>5000 or so) (unlikely), am fixing. If you get this problem increasing your buffer size in rendering/limits/buffers/gles2_2d_batch_buffer_size may fix it. Let me know any other bugs, there will probably be a few (hence need for test build!) :grin:

@lawnjelly - Does this work with the Sprite3D node?

@lawnjelly Did some testing with Jetpaca. The game uses big tilemaps, but zoomed in a lot around the player, so I don't see much FPS difference with and without batching - performance is great either way (~550 FPS on Intel HD Graphics 630 on Mageia 8).
The area where this game can benefit from batching is within the editor, as some of the big tilemaps can make FPS tank a lot in the editor. I've tried the allow_in_editor option but I don't see any difference, I wonder if the option works?

Blank scene: 139 FPS
Heavy scene (e.g. stages/alpha/alpha_Level_006.tscn): 35 FPS

(Note that use_vsync should be disabled to go above 60 FPS of course.)
Some other big tilemaps have good performance (> 100 FPS) like alpha_Level_011.tscn, so I guess some of the Nodes used in the scene as props have a big performance impact.
(Right, just tested and deleting the "Moving Platforms" parent node boosts performance to 137 FPS, almost like an empty scene.)
Still, no difference visible whether batching in editor is enabled or not.

Otherwise I tried the Text Rendering demo and my results are similar to yours.
~4 FPS without batching and 5 blocks of text, ~200 FPS with batching.

@lawnjelly Did some testing with Jetpaca. The game uses big tilemaps, but zoomed in a lot around the player, so I don't see much FPS difference with and without batching - performance is great either way (~550 FPS on Intel HD Graphics 630 on Mageia 8).

I tried jetpaca 2 or 3 weeks ago, it doesn't have many drawcalls so isn't bottlenecked by need for batching. Not all games will benefit. Essentially, if it is only spending 1% of time in the API calls, then a 100% speedup due to batching will only make game 1% faster. The big gains come when games are spending more time in the API calls, which can be identified by profiling (or trying it!).
On the allow_in_editor option - Using with jetpaca may not produce benefit if it is not drawcall limited. Also the option is rather unfriendly to use (and not intended for production), you must have batching switched on before you choose allow_in_editor.
I should probably make this more user friendly, it was rather hastily added as a project setting, and is probably more for me and clayjohn to test things rather than general use, and is more for finding regressions in the editor at this stage (rather than for general editor speedup). There are lots more bottlenecks for performance in the editor aside from rendering, we would need to profile to identify these.

I should probably make this more user friendly, it was rather hastily added as a project setting, and is probably more for me and clayjohn to test things rather than general use, and is more for finding regressions in the editor at this stage (rather than for general editor speedup). There are lots more bottlenecks for performance in the editor aside from rendering, we would need to profile to identify these.

A priori I used the options correctly (enabling allow_in_editor together with use_batching). But to be sure in future tests, you could add a print_line at the end of the initialize() method that summarizes what batching options are active.
I'd also suggest renaming flash_batching to flash_batching_debug or debug_flash_patching to make it clear that it's a debugging option and not a quality option (despite the name of the category -- btw we might want to move all those options to a dedicated category instead of rendering/quality maybe?).

I should probably make this more user friendly, it was rather hastily added as a project setting, and is probably more for me and clayjohn to test things rather than general use, and is more for finding regressions in the editor at this stage (rather than for general editor speedup). There are lots more bottlenecks for performance in the editor aside from rendering, we would need to profile to identify these.

A priori I used the options correctly (enabling allow_in_editor together with use_batching). But to be sure in future tests, you could add a print_line at the end of the initialize() method that summarizes what batching options are active.
I'd also suggest renaming flash_batching to flash_batching_debug or debug_flash_patching to make it clear that it's a debugging option and not a quality option (despite the name of the category -- btw we might want to move all those options to a dedicated category instead of rendering/quality maybe?).

Yup those are good ideas I'll do that right now, and try and improve the logic for allow batching. Ideally for the editor it would be nice to be able to change the options on the fly, which it cannot do at the moment, is there any way of getting a message from the main engine when the project_settings have been changed, or is reading them once per frame the best option? Let me know on IRC actually better there than here. :+1:

@HeadClot The Sprite3D node is unrelated to this. Its low performance is due to the use of ImmediateGeometry, which means it will generate its geometry every frame. As a workaround, use a MeshInstance with a PlaneMesh or QuadMesh attached. See #20855.

Just downloaded @akien-mga build and run my game project. After a couple of seconds, the game just froze. No messages in console. The only messages I got after closing project:
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112
WARNING: cleanup: ObjectDB Instances still exist!
     At: core/object.cpp:2091
ERROR: clear: Resources Still in use at Exit!
   At: core/resource.cpp:476
ERROR: There are still MemoryPool allocs in use at exit!
   At: core/pool_vector.cpp:69

Unfortunately I dont have minimum reproduction project, I only have this console message. I didnt do any changes in ProjectSettings.
Desktop: Win10, 1050ti mobile, i7-7700HQ

Just downloaded @akien-mga build and run my game project. After a couple of seconds, the game just froze. No messages in console. The only messages I got after closing project:
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112
ERROR: ~List: Condition "_first != __null" is true.
   At: ./core/self_list.h:112
WARNING: cleanup: ObjectDB Instances still exist!
     At: core/object.cpp:2091
ERROR: clear: Resources Still in use at Exit!
   At: core/resource.cpp:476
ERROR: There are still MemoryPool allocs in use at exit!
   At: core/pool_vector.cpp:69

Unfortunately I dont have minimum reproduction project, I only have this console message. I didnt do any changes in ProjectSettings.
Desktop: Win10, 1050ti mobile, i7-7700HQ

I'm not immediately sure what might be causing this, given the output, although perhaps the output is a red herring. Have you tried disabling batching in projectsettings/rendering/quality/gles_2d_batching/use_batching? This should let us know whether the problem is due to the batching or something else.
Are you able to successfully run a different simpler project with batching (e.g. the 2d platformer demo, that works fine on mine)? Is it any project with batching or something to do with this particular one? Anything you can work out that seems to be associated with the problem will help me make a min reproduction project.

Looks like this error message is not caused by batching (same output message with batching disabled).
I think I found out what caused freeze: it is draw_texture. Because project below not just freezed by itself, but also permanently freezed entire PC (that's why i dont want to try it second time :D ). But without batching it works ok.
Tested with this project:
bunnymark.zip
Steps (or maybe not) to reproduce: Run project, switch to another window, switch back to project window, reboot you PC :D
(PS: Maybe i have wrong drivers, and there's no error in godot)

Looks like this error message is not caused by batching (same output message with batching disabled).
I think I found out what caused freeze: it is draw_texture. Because project below not just freezed by itself, but also permanently freezed entire PC (that's why i dont want to try it second time :D ). But without batching it works ok.
Tested with this project:
bunnymark.zip
Steps (or maybe not) to reproduce: Run project, switch to another window, switch back to project window, reboot you PC :D
(PS: Maybe i have wrong drivers, and there's no error in godot)

I'll see if I can track this down further. I've been using bunnymark in testing and also draw_texture I believe, I don't think they are doing anything special but I'll double check and see if I can reproduce the problem my side. You may be correct and it could be a driver issue from the switching window description, but I'll see if I can guess what it might be and whether there is a workaround, sometimes we can make small changes on our side and it keeps the driver happier.

@lawnjelly also please take a look at shader project below

UPD2: Another bug/feature - batching breaks simple color mix shader (enabled allow in editor and flash batching):

MRP to UPD2:
Test.zip

@lawnjelly also please take a look at shader project below

UPD2: Another bug/feature - batching breaks simple color mix shader (enabled allow in editor and flash batching):

MRP to UPD2:
Test.zip

Ah well spotted I'll see if I can fix that! :+1:

This is just freaking awesome!
My scene consists out of 4 layers of parallax background, 3 layers of tilemaps and a few animated sprites. The gain is unbelievable.
Before: ~1700 FPS
After: ~3500 FPS
Specs:
Intel(R) Core(TM) i7-8705G CPU @ 3.10GHz
Radeon™ RX Vega M GL

I've tried different "bunnymarks" (a lot of sprite nodes moving around the screen) and didn't notice any difference. Does it apply to that case?

I've tried different "bunnymarks" (a lot of sprite nodes moving around the screen) and didn't notice any difference. Does it apply to that case?

It does, but it may depend which tests. Quick result on the current PR:
Bunnymark V2 GDscript
Old 3400 Batched 8160 (2.4x faster)
Bunnymark V1Sprites GDScript
Old 3340 Batched 7180 (2.15x faster)
I've had it running faster on bunnymark, but the emphasis at the moment is on fixing regressions.
Bunnymark in general is not a good benchmark for rendering performance, only a small proportion of the time is in the drawcalls, if you profile it you will see. If you purely test on render_items with batching you will get higher increases. See the section in my first post on bottlenecks.

For me it is slower but I am not using tilemaps or tons of sprites, maybe in my case I won't see any benefits, I mean I am still running over 4k FPS.
Godot 3.2 stable                            - 5000 ~ 4500
Godot 3.2 2d Batch Render           - 4900 - 4300
Specs
PopOS 18.04 64-bit
16GB RAM
Intel I7 4790 3.6GHz * 8
Geforce GTX 1060 6GB
I didn't face any bug.
I've recorded my test if it somehow could be useful https://youtu.be/yiLQz8dMsc0

@ricardoalcantara Batching will only improve your framerate if you are bottlenecked by drawcalls. If you are getting 5000 FPS you are definitely not bottlenecked by draw calls and shouldn't expect any benefits.
Glad to hear you aren't seeing any regressions. Thanks for testing! :)

For me it is slower but I am not using tilemaps or tons of sprites, maybe in my case I won't see any benefits, I mean I am still running over 4k FPS.
Godot 3.2 stable - 5000 ~ 4500
Godot 3.2 2d Batch Render - 4900 - 4300

Yes as clayjohn says, there won't be any scope for improvement there as you are probably only using in the region of 10-20 drawcalls. :grinning: You could try the light scissoring though if you are using lights (I'm not sure that you are though).
To answer the general question, and this is mostly theoretical:

It is possible a benchmark with a large number of items could be designed to get a slight drop in performance compared to old, if it did everything possible to prevent batching, as the batching calculations do have a slight cost, but this is very unlikely in the wild.
There also could be small differences to do with how efficiently the GPU dealt with indexed primitives versus the old approach with vertices passed via uniforms in some extreme circumstances.
There could be a bug in the batching, for instance having a more expensive texturing state in the batching versus the old, however I'm not convinced you are seeing this.

In your case the most likely cause of differences is that you are comparing different builds. Even minor changes in compiler version between builds can produce quite large differences in frame rate (I had a 10% boost with a different version of llvm for example), and there also may be other PRs that differ between the builds. So when comparing, I would just turn batching on and off within projectsettings rather than compare against another build.

@arkology :

UPD: Increasing gles2_2d_batch_buffer_size fixes the problem

Ah this is hugely helpful! :+1:
I was just going to say that I've fixed all the other regressions (but not pushed etc yet) but the freeze is still outstanding and potentially the most tricky. But if increasing the buffer size fixes it, that helps pinpoint what might be the problem, I've already fixed one bug dealing with the buffer overflow condition (although I don't think that fix will deal with the freeze, that bug only made the transforms incorrect which is fairly harmless).
I'll try and do some tests here and see if I can find anything going astray in the buffer overflow condition. It is hard to diagnose remotely but I'm sure we will find a solution.

All the other regressions are fixed now and pushed and reduz's changes. Now I'll see if I can track down what is causing arkology's freezing. Any more bug reports / regressions are welcome.
Also testing on other platforms, especially iOS and Mac if anyone has those would be useful, even reports of it working successully. :+1:

I tried to understand in more detail how this freeze appears. (Tested with akien build and bunnymark project)
Works without any problems with integrated (Intel HD Graphics 630) card - so it happens only with 1050ti mobile.
No need to switch to another window. You'll get this freeze anyway. So maybe it is not connected.
Now I'm not sure that increasing batch buffer size fixes the problem - it still exist.
... After drivers update (my drivers were pretty outdated (really outdated, 2018y), but they worked, so i didn't update them until this moment):
Now bunnymark project doesnt freeze PC permanently - just for 1-2 seconds, sometimes longer. After freeze there are 2 different behaviors: 1. project will continue working as normal, or 2. project will freeze permanently.
There were 2-3 times when i could not even run Godot ProjectManager, although use in editor is turned off.
The most reproducible thing i got - no freezes if you dont touch running bunnymark window. Freeze appeares after moving bunnymark window. And this is the only more or less stable results after ~ hour of testing.
But the truth is that i cannot make this freeze fully reproducible. Sometimes it acts like i described above, sometimes not, its fully random (except window moving, it's half random :] ). So everything above may be wrong. Too random behavior, and it makes me feel useless as "tester" :D
The only thing i can say (i hope) for sure:

Works without this freezes with integrated videocard.
After drivers update there're no more permanent PC freezes.

Well it is much appreciated, I prefer to investigate such things rather than write them off as driver issues, sometimes we can pinpoint what is causing the behaviour and use an alternate technique.
Aside from an obvious bug on my side, it could be having problems with the multiple orphan buffers per frame (if the graphics driver is not made to deal with this). This can potentially stress the allocation / deallocation strategies, which is why I tend to usually reuse fixed pre-allocated buffers as an alternative.
I'll keep you posted and see if I can work out what might be going on. :+1:

I have several scenes on my game to benchmark different options.
I put on the scene lots of sprites to see how the logic works, so I used that benchmarks. On my first try, batched tests were slower, but then I tried something: I use the modulate attribute to change the sprites colors, so I tried not to use modulate and then I had a great speed increase.
Testing on Windows. FPS moving 3000 objects with raycast collision detection:
· No batch: 100-130 FPS
· Batch, different colors for each sprite: 60-69 FPS
· Batch, not using modulate: 240 FPS (nice)
Testing on Android. Max objects with raycast collision detection with 60 FPS:
· No batch: 1700 objects
· Batch, not modulate: 2000 objects
So far, so good. Totally worth it

@adeluiz could you try that first scene again with different values of "colored_vertex_format_threshold"?

@adeluiz could you try that first scene again with different values of "colored_vertex_format_threshold"?

Sure! And then I will try the same tests on an old Macbook Air (I've just seen your request)

Testing on Windows. FPS moving 3000 objects with raycast collision detection:
· No batch: 100-130 FPS
· Batch, different colors for each sprite: 60-69 FPS
· Batch, not using modulate: 240 FPS (nice)

I'll see if I can replicate this case (with the slowdown) and deal with it. Maybe the colors is breaking the join_items when it shouldn't. It sounds quite fixable. :+1:

@arkology As lawnjelly mentioned above, it sounds a lot like your issue is caused by the GPU overheating for a few reasons:

Only occurs with v-sync off (v-sync limits the amount of work your GPU does per frame)
Your using a mobile GPU (presumably in a laptop with poor ventilation)
The driver update reduced how often the freezing occurs (making it seem like a driver/hardware specific issue)
The project manager/editor are freezing as well, even though batching is turned off

These reasons really make it seem like your GPU is overheating and then freezing all processes. It sounds like you also have an intel integrated chip which all the other programs on your computer are using.
To test this theory you have 2 options:

Test the batching PR as before (with v-sync off) but cool your computer manually (e.g. open it up, surround it with fans, place it outside etc.)
Run another GPU intensive program with v-sync off and force it to always use your dedicated GPU and see what happens.

Please try the above and update us on what happens!
ps: There may also be settings in the NVidia control panel that would alleviate the effect of the overheating, if that indeed is what is happening.

I suggest to just run Speedfan and check temperatures :)

More testing. Old macbook air. All working fine.
1000 bouncing sprites:
· No batching: 92 FPS
· Batching: 221 FPS (Yes!!!)
· Batching with modulate: 63 FPS
· Batching with modulate and "colored_vertex_format_threshold" = 0.75: 72 FPS

@adeluiz Thanks for the confirmation.
I put together a test script to reproduce the issue with modulate:
extends Node2D

func _ready():
	for i in range(10000):
		var sprite = Sprite.new()
		sprite.texture = load("res://icon.png")
		sprite.modulate = Color(randf(), randf(), randf())
		sprite.position.x = randf()*1024
		sprite.position.y = randf()*600
		add_child(sprite)

The above code results in ~90FPS without batching and ~15FPS with batching(~350 with modulate line commented out).
@lawnjelly When you are available, let's chat about how to speed up the modulate code-path.

@lawnjelly When you are available, let's chat about how to speed up the modulate code-path.

Yup sure, I was able to reproduce it too last night with similar script. Am going to investigate today, I think we may be able to just apply the final modulate via the vertex colors and batch as normal in such cases, but I'll have to take a look at the shader.
Otherwise we can mitigate it by recognising early and taking a simpler path. I'm going to profile because I can't immediately see how it has managed to slow it down that much (I'd be more expecting a max of a few percent drop), there's probably something bugged in there. Even worst case it should only be a few extra state checks per render_item and single indexed rect versus the old uniform technique.

I can’t show the test results now (so I’ll update the comment later. The results sound something like “ I should not use Godot with dedicated videocard without v-sync or limiting framerate”, and not because of overheating, furmark runs great), but looks like it is not batching issue, hooray!

Well firstly I'd like to thank you loads @arkology for helping to pin this down. :+1:
Even though it doesn't seem to be due to batching (or overheating), imo it is well worth creating a separate issue for, because there is clearly something in Godot which isn't playing right with your 3d card, and this may be happening to others too. I'm happy to continue with the investigations in another github issue, if you fancy some detectivework! :grin:

Hmm... 60 degress doesn't sound to me like a huge temperature if under load... 80+ is bad, but 60 is quite alright I think

Testing on Windows. FPS moving 3000 objects with raycast collision detection:
· No batch: 100-130 FPS
· Batch, different colors for each sprite: 60-69 FPS
· Batch, not using modulate: 240 FPS (nice)

I've now got it batching with different colors per sprite too, it should be close to 240 FPS for that case too. Baking the final modulate color into the vertex colors worked perfectly, then it just batches as normal. :+1:
It was a little more involved to pass this final_modulate value through the code so I will clean it up and do some more testing tomorrow before pushing.

New edge case! For some reason it isn't batching when all the Sprites share an AtlasTexture but is batching when all the Sprites share a regular Texture.
To test: Add a Sprite with an AtlasTexture, duplicate thousands of times, run with and without batching and notice that there is no FPS change.

Looks like the bottleneck in this scene just wasnt draw calls. It was using a small section of a large atlas. Switching to using a small texture in the atlas was enough to see the difference.

I can't seem to replicate it, although I've never used texture atlas before so don't know if I'm doing it correctly. I chose texture atlas for the sprite then chose a 2048x2048 texture, then made the region width and height 64. I'm still getting the same 9x speed improvement with this as with a regular texture.
As you say it may just be in this case for you the rendercalls is not the bottleneck. If there's a single drawcall then the batching would seem to be working fine.
The fact that even without batching the use of the atlas texture drops FPS from 700 to 400 suggests there might be something else going on.

Test build 2
https://downloads.tuxfamily.org/godotengine/testing/3.2.2-gles2_batching_build2/
Built from df87601c8818b9978ae7718c71d614eed3f5959b + this PR as of today (e7bec77ef36c2f5bc9da96d0adfe34f98223c9ed).

Something seems broken with the export templates. I had to install, then rename them in order to be detected as installed.
From:
C:\Users\myuser\AppData\Roaming\Godot\templates\3.2.2.gles2_batching_build2
to:
......\3.2.2.rc

Something seems broken with the export templates. I had to install, then rename them in order to be detected as installed.
From:
C:\Users\myuser\AppData\Roaming\Godot\templates\3.2.2.gles2_batching_build2
to:
......\3.2.2.rc

Indeed, I forgot to commit the version.py change that would brand it differently. I'll reupload the templates with fixed version.

Edit: I'm uploading updated .tpz templates now, don't download right now as they would likely be corrupted (upload and replication should finish in ~20 min).

The fixed export templates are now up at the same address.
Note that this "gles2_batching_build2" release will still report itself as "3.2.2.rc.official" since I messed up the version.py changes before the build, but I can confirm that it corresponds to the commits listed in https://github.com/godotengine/godot/pull/37349#issuecomment-610822995.

My first test:
i3 2120; gt630 1Gb
places where it used 28% of the gpu is around 21 ~ 23%.
In normal mode I had peaks of up to 31%, with this engine it was no more than 23%. My project is not using gpu a lot, even so I noticed an improvement that deserves to be commented on !. At night I will test on my ryzen 1600 machine; gtx1060, which by the way is suffering from flashing tiles.

Every 0.1 second a new RigidBody2D is spawned in the level (always with the same sprite).
Test duration: 40 seconds.

--- 2D batching ---
Total frames = 67'378
AVG = 1684 FPS

--- No batching ---
Total frames = 47'975
AVG = 1200 FPS

--- hardware/software ---
CPU: 6-Core Intel Core i7-9750H
Kernel: 5.5.13-1-MANJARO x86_64
Mem: 7597.9 MiB
Device-1: Intel UHD Graphics 630 driver: i915 v: kernel
Display: x11 server: X.Org 1.20.8 driver: intel unloaded: modesetting
OpenGL: renderer: Mesa DRI Intel UHD Graphics 630 (Coffeelake 3x8 GT2)
  v: 4.6 Mesa 19.3.5

Tests done on angry-aliens/tree/gles2-test/Scenes/StressTest.tscn.
.csv debug data available here: https://docs.google.com/spreadsheets/d/1D3wDrXjjGbAI-PbztYwVU4eF3_aDRXY5ylqzz8hYqfk/edit#gid=501292352

Every 0.1 second a new RigidBody2D is spawned in the level (always with the same sprite).
Test duration: 40 seconds.

That's encouraging that you are still getting a decent gain, because afaik that should be just about one of the worst scenarios for the batching .. one sprite per node and physics on it too (which I'd have expected to overshadow the costs of rendering). :+1:

Just tried the newest test build, it works fine for my GLES2 project Mortyverse and I'm using a ton of tilemaps.
The HTML5 build went from 20 -> 40 FPS which is pretty great, there did not seem to be anything wrong with any of the tilemaps or sprites.
(The horrible performance is because I'm rendering 4 2D scenes to 3D planes simultaneously, all of which have several layered tilemaps).

I test "Godot_v3.2.2-gles2_batching_build2_win64.exe.zip | 2020-Apr-08 09:50:11 | 27.0M | application/zip" in a 2D fight game project and i see no regresions... but not performance increases turning on batching (literally 0). All that renders to screen are sprites and animated sprites.
However, in a test font scene of my project, performance go from 1100 to 1800 fps. The proofs:
Without batch:

With batch:

So, please press merge button!!!!! worth it!

I test "Godot_v3.2.2-gles2_batching_build2_win64.exe.zip | 2020-Apr-08 09:50:11 | 27.0M | application/zip" in a 2D fight game project and i see no regresions... but not performance increases turning on batching (literally 0). All that renders to screen are sprites and animated sprites.
However, in a test font scene of my project, performance go from 1100 to 1800 fps. The proofs:

It sounds like you weren't using enough drawcalls to be bottlenecked (or maybe you weren't using rects? only rects are batched so far), but no regressions is always good news. And it does seem to be working with your test font scene. :+1:

Other test. A random map generator (Single tilemap).

In a isometric test scene with some overlaped tilemaps, batch has slightly worst performance that not batch (batch 600 aprox, no batch 700 fps):

This might be a scene that it can't batch at all. We can do some improvements to try and get this worst case at least as good as the non-batched version. You can try setting max_join_items to 0, which may help slightly. Otherwise it is probably down to some extra redundant state changes we can remove, or the slightly different draw method versus the old.
Although the worst case scenario is well worth dealing with, in this case, this may be something that can be fixed in game to enable it to batch. Different textures / materials for instance will break the batching, so using a texture atlas will help if you are not already. Different z values could also be the culprit, the batching may not work across different renderer z values. If this is the problem, if you are able to just order the items yourself rather than rely on renderer z it may enable batching.
I'll try and have a look and see if there is a way around this renderer-side (it may not be possible but is worth a look).

This might be a scene that it can't batch at all. We can do some improvements to try and get this worst case at least as good as the non-batched version. You can try setting max_join_items to 0, which may help slightly. Otherwise it is probably down to some extra redundant state changes we can remove, or the slightly different draw method versus the old.
Although the worst case scenario is well worth dealing with, in this case, this may be something that can be fixed in game to enable it to batch. Different textures / materials for instance will break the batching, so using a texture atlas will help if you are not already. Different z values could also be the culprit, the batching may not work across different renderer z values. If this is the problem, if you are able to just order the items yourself rather than rely on renderer z it may enable batching.
I'll try and have a look and see if there is a way around this renderer-side (it may not be possible but is worth a look).

Your work is worth it now.
The isometric test scene has a lot of "test" things: Tilesets with an atlas, Tilesets with images with regions, with several images, different sizes, etc... So i think is normal that not batch at all.
My fight scene has a parent "Y-sort", maybe this is the cause of not batching... however, i have not bottleneck on rendering, and I haven´t text or tilemaps on screen now, probably when the game is finished, there will be a lot of things that can benefit of batching.
I test all my "test" scenes and menus, and my conclusion is that, with batching, the mayority of times there is an increase of 50-100% in performance, but sometimes, there is an slightly decrement of 5-10% in performance. Being an optional project setting, this is 100% worth it definitely. And no regression detected.

I think I have detected another weird behaviour. With batching on and 3000 sprites on screen I have 240 FPS, but if I turn the VSync on, it goes down from 240 FPS with 2000 objects to 40-60 with 3000 (I am using a 240 Hz monitor). I have replicated the same behaviour with build 1, so it is not a regression.

I think I have detected another weird behaviour. With batching on and 3000 sprites on screen I have 240 FPS, but if I turn the VSync on, it goes down from 240 FPS with 2000 objects to 40-60 with 3000 (I am using a 240 Hz monitor). I have replicated the same behaviour with build 1, so it is not a regression.

Hmm, what is the behaviour with batching switched off (in project settings/rendering/gles2/use_batching)?
I'll see if I can wrap my head around what is happening! :grinning: It may be a consequence of just missing the frame, but then you would have thought it would go to 120 FPS...

I test all my "test" scenes and menus, and my conclusion is that, with batching, the mayority of times there is an increase of 50-100% in performance, but sometimes, there is an slightly decrement of 5-10% in performance. Being an optional project setting, this is 100% worth it definitely. And no regression detected.

The drop in performance is happening when it's totally failing to batch, and the batching path with 1 rect is currently not as optimized for state changes etc as the old path (which is designed to work with a single rect only).
It's very tempting to be lazy and just use the old rect drawing routine in this worst case (as it should have the same FPS) but we would ideally like to remove that bit of code so I'll see if we can get the new path working decently even with a single rect. :+1:
In some cases when we find these worst cases it's possible to get them to work with the batching (as we did with modulate on sprites) in which case you will get full acceleration.

I haven't noticed performance gains from using batching while drawing the same texture with:
draw_set_transform(offset, 0.0, Vector2.ONE)
texture.draw_rect_region(get_canvas_item(), dst_rect, src_rect)

In fact I get like 50% slowdown with batching on (16 FPS without batching, 8 FPS with batching). I'm not sure whether my use case can be improved with this PR in the first place though. GLES3 does better overall (26 FPS).
I'm drawing bezier curves with a single texture along that curve (the texture is 10x10 pixels)

Test project
BezierCurveBatch.zip
I'm obviously stress testing this but I'm trying to use this technique in a real project to some extent (like drawing some fancy hands/legs and being able to animate them dynamically).

I haven't noticed performance gains from using batching while drawing the same texture with:

I'm just currently working on speeding up the worst case where it can't batch. If necessary we'll just use the old drawing code for that.
But I'm hoping I can get a lot of these cases to batch (including possibly the z_index case with the isometric map), I'll have a look at your project. :+1:

I haven't noticed performance gains from using batching while drawing the same texture with:
draw_set_transform(offset, 0.0, Vector2.ONE)
texture.draw_rect_region(get_canvas_item(), dst_rect, src_rect)

In fact I get like 50% slowdown with batching on (16 FPS without batching, 8 FPS with batching). I'm not sure whether my use case can be improved with this PR in the first place though. GLES3 does better overall (26 FPS).

I'm just having a look now at accelerating this case.
While I've now got worst case to roughly the same as the old renderer, I figured out you can get batching to work with it by changing your code to this (I'm presuming, I've made a couple of changes since the last build):
		#draw_set_transform(a, 0.0, Vector2.ONE)
		var dst_rect_moved : Rect2 = dst_rect
		dst_rect_moved.position += a
		texture.draw_rect_region(get_canvas_item(), dst_rect_moved, src_rect)

This avoids the transform and stores the position directly on the rect.
This increases FPS from 19fps (old) to 34fps (batched). Normally I'd expect a greater increase, there might be something else going on here, maybe it's batching each bezier curve but not between curves, I haven't fully investigated yet.
This doesn't take away from that it would be useful to accelerate with the transform too, because you can't use a rotate with this above technique, so I'll try and get that working. :grin:

This avoids the transform and stores the position directly on the rect.
This increases FPS from 19fps (old) to 34fps (batched).

That's great news indeed. I want to tell that even on GLES3 this alone increases FPS by 7 on average which I'm currently on (planning on switching to GLES2 because of enhancements like this PR), so thanks for that solution! There are certainly places where I can optimize with this technique.

This doesn't take away from that it would be useful to accelerate with the transform too, because you can't use a rotate with this above technique, so I'll try and get that working.

Yeah the above test project only scratches the surface of what can be done with such a texture drawing along the curve. Certain directional textures like "arrows" need to take advantage of rotation, and certain indicators can be drawn with linear bezier which need scale modifications as well (that's just linear interpolation). Take this abstract creature:

Would be nice if this is possible, especially with arbitrary transformations like these.
Test project
Updated the project to easily test different scale/modulation for texture drawing along the curve as seen above.
BezierCurveBatchUpdated.zip

Would be nice if this is possible, especially with arbitrary transformations like these.

I have this working now, preliminary at least, I need to test more and check for regressions as the logic is quite complex. The increase is from 18-31fps. Not quite as much as the more efficient method I mentioned earlier of not using transform.
However, in your benchmark (with the bezier curves), note that the rendering isn't really the bottleneck. In fact profiling a release build (with the batching working), only 2.33% of the CPU time is spent doing the actual rendering. A lot of the time is spent in gdscript:

This is common in a lot of these benchmarks (e.g. bunnymark). GDScript works great for the usual numbers of objects you might be using in a game (e.g. 50 or so), but it doesn't scale well so you'd usually want to look at alternative ways of iterating / drawing things when you are thinking about large numbers of objects.

Nice findings, well yeah I kinda suspected this being a GDScript thing to some extent, but is the profiling was done with _process() commented out or was it actually processing draw commands each frame? I always assumed that when you _draw() (update()) once, those draw commands end up being stored and executed outside of GDScript calls, or am I wrong on this assumption?
Either case, I'm a "GDScript-to-C++" junkie already so I'll likely port this. I've done the same when I was working on image bucket fill implementation, had like x35 gains from avoiding script calls! (set_pixel etc).

I always assumed that when you _draw() (update()) once, those draw commands end up being stored and executed outside of GDScript calls, or am I wrong on this assumption?

I think this is correct, but you are calling update() during _process, which is rebuilding all the draw stuff each frame. If I comment out the update() during process, the frame rates are now:
Non Batched:
With update: 18fps No update: 39fps
Batched
With update: 31fps No update: 580fps
As you can see when you are measuring the rendering performance more (and not the gdscript etc, the frames per second has gone up by nearly 19x. :wink:

Yeah, I think I just forgot to comment out the _process call, so sorry for the confusion!

With update: 31fps No update: 580fps

This alone makes me want to switch to GLES2, hopefully I can switch to 4.0 too. 😁

CPU usage in project - https://github.com/godotengine/godot/files/4211078/Text.Wrap.Test.zip from #36287, decreased from 12% to 3%.

CPU usage in project - https://github.com/godotengine/godot/files/4211078/Text.Wrap.Test.zip from #36287, decreased from 12% to 3%.

Turn off vsync and print the FPS, that gets you:
Without batching : 7 FPS
With Batching : 520 FPS (74x speed increase)

Just tested with recent changes to this PR in a project of mine.
At first I thought there's no significant gains, but I couldn't believe that.
Unfortunately, the drawing API doesn't provide a way to simulate different z-index within the _draw method itself, which I'd imagine would look like this:
func _draw():
	draw_set_z_index(zi)
	# ... draw textures on different z_index within the same CanvasItem

Instead, I had to basically split up the same class and use different draw offsets/ranges:

Which I suppose does "harmful" things performance-wise when this is split between canvas items.
This is where I had a drop in performance once again, but I have to say that in either case, GLES2 with batching performs better/on par with GLES3.
But good news is that, without the splitting hack (only drawing an entire arm within a single canvas item), I'm able to draw around 300 characters on screen before FPS goes below 60 (was only able to render around 80 characters on GLES3).
Having said that, I'm totally satisfied with the performance gains, and some optimizations are possible to achieve on the per-project level now (both rendering and GDScript bottlenecks), so thanks for the work you've put into this @lawnjelly, hopefully my testing efforts wasn't in vain. 😁

Yeah, I can't say without examining your new project what your new bottlenecks are. It could be

the way you are updating the visual server, which was the bottleneck in the previous version (taking > 10x longer than the actual rendering)
it could be a situation that isn't covered
or it could be that you are now producing something which is not possible to batch.

There are limitations as to what can be batched in order to preserve the behaviour of the previous renderer, and not have visual regressions.
The updating of the visual server did look very slow in your bezier approach and it is worth an investigation, but it is outside the scope of this PR.
I think the aim here should be to at least cover the most popular use-cases, and as many generalised use cases as possible. If you are using quite bespoke techniques you may have to experiment a bit to find out what works best.
Profiling is really useful for this kind of thing, especially if you can compile from source.
That reminds me I'm intending to add some diagnostics within the IDE to help with this kind of thing. I believe the 'monitor' tab of the Godot IDE didn't work at all for GLES2 2D before, but I'll try and get it to correctly monitor the number of drawcalls and whatever else is possible. I may be able to get it to debug print out some diagnostics for a frame, I'm not sure yet though, it would depend on some method to call from the IDE or script.

Unfortunately, the drawing API doesn't provide a way to simulate different z-index within the _draw method itself

Yes, the z index is set for the entire item (usually a node), and not the commands within it. However afaik if you order the drawing commands yourself, this order will be respected in the renderer. And it will probably be more efficient to boot (providing you do your sorting efficiently your side).

On suggestion from Akien I've now changed use_batching_in_editor to default to true.
I've also added (in the same commit) some very basic features to the IDE Debugger monitor:

2d/items - number of canvas items, or joined canvas items using batching
2d/draw_calls - number of draw calls

These are particularly useful for getting batching working as well as possible in your game, because you can see the drawcalls reduce dramatically the more batching you are achieving. It also operates with batching switched off.
The alternative is to reuse 'drawcalls' in the raster section (if adding new values might e.g. affect the efficiency of the debugger), but a new section is preferable if possible because it enables you to examine 2d and 3d in isolation in 3d games which have 2d user interfaces. It also may be possible to add more performance stats but this should do to start with.
I haven't implemented these for GLES3, but that should be fairly simple to use the same mechanism.
I'd also appreciate anyone familiar with the Debugger monitor looking over how I added the values in this commit. I literally did a find_in_files for existing values until it worked, so I can't guarantee I've done everything correctly, particularly whether it might affect monitoring over network.

Just as a final tweak, based on the conversation last night with @clayjohn, I've added a simple frame diagnostics mode. You can turn it on and off in the project settings rendering/gles2/debug/frame_diagnostics.
When set to on it prints every 10 seconds a log of the batches being used in the frame, in this example form:
canvas_begin FRAME 4716
items
	joined_item 2561 refs
		batch D 0
		batch R 2560 [0] MULTI
		batch R 12 [1] MULTI
	joined_item 1 refs
		batch D 1
	joined_item 1 refs
		batch D 0
		batch R 6 [0] MULTI

This shows how successful the item joining is, and whether the batch is default (D) or rect (R), then number of items in the batch, the batch tex ID in square brackets, and a MULTI symbol is there are multiple rects in the batch. The aim should be to get as many MULTIs as possible.
Projects that are not batching well will have a lot of single rect batches. Note that complex games will have quite long frame logs, in which case they might get truncated by the editor. You can either run godot from a console to see the full log, or you can increase the IDE buffer size by increasing network/limits/debugger_stdout/max_chars_per_second.

Looks good to me.
Let's get this merged and tested in production :metal:
Thanks a ton for the tremendous work @lawnjelly, @clayjohn and all testers!

WARNING: render_batches: NinePatch without texture not supported yet in GLES2 backend, skipping.
At: drivers/gles2/rasterizer_canvas_gles2.cpp:883
I am having this error when I try to create an AtlasTexture in a Custom Style of a Panel.

AVISO: render_batches: NinePatch sem textura ainda não suportada no back-end do GLES2, pulando.
Em: drivers / gles2 / rasterizer_canvas_gles2.cpp: 883
Estou tendo esse erro ao tentar criar uma AtlasTexture no estilo personalizado de um painel.

Panel -> Custom Styles -> StyleBoxTexture -> Texture -> New AtlasTexture.

WARNING: render_batches: NinePatch without texture not supported yet in GLES2 backend, skipping.
At: drivers/gles2/rasterizer_canvas_gles2.cpp:883
I am having this error when I try to create an AtlasTexture in a Custom Style of a Panel.

Despite the function name, this area is just copy pasted from the old renderer (to reuse the same code between the legacy and batched renderer). I suspect the old renderer would do the same (if you switch off use_batching), or compare with e.g. Godot 3.2.1.

[light_scissor_area_threshold]
A value of 0.0 means any area saved will activate scissoring, 0.5 is half the screen etc. The actual pixel area is calculated regularly in case the user resizes the screen.

Is 0.5 half the screen or quarter?  If you're dividing the X and Y by 2 or multiplying by 0.5 it's quarter, You'd have to divide by 1.4142~ or multiply by 0.7071~ to actually get half screen res. It's an important distinction for documentation.

[light_scissor_area_threshold]
A value of 0.0 means any area saved will activate scissoring, 0.5 is half the screen etc. The actual pixel area is calculated regularly in case the user resizes the screen.

Is 0.5 half the screen or quarter? If you're dividing the X and Y by 2 or multiplying by 0.5 it's quarter, You'd have to divide by 1.4142~ or multiply by 0.7071~ to actually get half screen res. It's an important distinction for documentation.

It's an area : width * height in all cases.

We have an AABB A for the light, and an AABB B for each item.
We can calculate the intersection area between the 2 C.
The area potentially saved by scissoring D, is B - C.
If the area saved D (as proportion of total screen pixels) >= light_scissor_area_threshold, then we apply the scissor

In this way we can selectively apply glScissor in cases which are likely to save a lot of fill rate. Or we can apply it in all cases (set to 0), or turn it off completely (1). On my PC there is not a massive cost to scissoring and setting it to 0 is quite viable. However it is possible that on some hardware there may be some cost to scissoring (at the very least, there is a couple of GL calls), such that the best value lies somewhere in between. I don't have the facilities to rigorously test this so the decision is left to the user.
We may later be able to automate some of these decisions to an extent, but it is hard to get feedback of the effects of changing this kind of thing without running e.g. some diagnostic tests at startup. This is similar to the problems faced by a car ECU.

Looking at rasterizer_canvas_gles2.cpp, shouldn't the orphaning code in _batch_upload_buffers()
// orphan the old (for now)
glBufferData(GL_ARRAY_BUFFER, 0, 0, GL_DYNAMIC_DRAW);

read like the orphaning done in the initialization?
glBufferData(GL_ARRAY_BUFFER, bdata.vertex_buffer_size_bytes, NULL, GL_DYNAMIC_DRAW);

I believe that the zero size results in an noop. When we introduced orphaning in GLES3 which gave the speed boost on mobile the rationale was to orphan the whole buffer.

This is a little bit of a gray area, as far as I am concerned. Generally I go with manually using a circular set of vertex buffers to make it explicit, but in this case we are reusing the same VB multiple times per frame so orphaning seemed easier.
https://www.khronos.org/opengl/wiki/Buffer_Object_Streaming
It seems the driver is able to do whatever it wants. Using the same size as before makes some sense if you are going to be reusing a similar sized buffer. However in this case, the buffer size will be varying each time so we don't gain much by doing that. In fact, it might be detrimental because it might decide to reserve some memory just in case you glSubBuffer to it.
I think I did try both and decided this made the most sense, but am willing to change it if we discover it causes problems (it has seemed fine so far). :+1:

It will work but that's not the point. The point of orphaning is to let the driver know that we're not interested in the previously allocated and written to buffer and that we're done with it. The first bind/unbind cycle says "go draw this data". The second time we do that, we may overlap with what is currently in progress, which is a nasty constraint for the driver and usually results in a slowdown (which is what I saw last time I dealt with that stuff). Unless we orphan the whole buffer, After the first bind/unbind cycle, the driver assumes that we may rebind and write to the buffer again. But if we say, bind(size, null) there is no other interpretation than "we're done with the whole previous buffer, we need a new one".  If we say bind(0, null), this means nothing significant as the buffer may be written to again and rebound. The latter is basically like a malloc(0) - no harm to the heap, no effect.

It will work but that's not the point. The point of orphaning is to let the driver know that we're not interested in the previously allocated and written to buffer and that we're done with it. The first bind/unbind cycle says "go draw this data". The second time we do that, we may overlap with what is currently in progress, which is a nasty constraint for the driver and usually results in a slowdown (which is what I saw last time I dealt with that stuff). Unless we orphan the whole buffer, After the first bind/unbind cycle, the driver assumes that we may rebind and write to the buffer again. But if we say, bind(size, null) there is no other interpretation than "we're done with the whole previous buffer, we need a new one". If we say bind(0, null), this means nothing significant as the buffer may be written to again and rebound. The latter is basically like a malloc(0) - no harm to the heap, no effect.

Afaik, glBufferData always should release the reference to the previous buffer and create a new fresh allocation (it presumably leaves a ref count on the previous object will get to zero once it has been rendered and is no longer owned). That's the difference between glBufferData and glBufferSubData. glBufferSubData is to update some part of the buffer. glBufferData is to say 'throw away what you've got and give us a new one, and upload this new data'.
Orphaning is probably more relevant when you want to use glBufferSubData in combination. If you don't do it in that scenario, presumably it has to do a load of housekeeping to keep the rest of the buffer the same (and may cause pipeline stalls). We are not doing that here, we are simply throwing out the whole of the old buffer.
https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glBufferData.xhtml

glBufferData creates a new data store for the buffer object currently bound to target. Any pre-existing data store is deleted. The new data store is created with the specified size in bytes and usage. If data is not NULL, the data store is initialized with data from this pointer.

Yes, you are right and I stand corrected. And that glBufferData(0, 0) seems spurious at best. The driver can't do anything meaningful with it as it's not even an early indication of whatever follows, which is an overwrite.

And that glBufferData(0, 0) seems spurious at best. The driver can't do anything meaningful with it as it's not even an early indication of whatever follows, which is an overwrite.

You are very probably right, I put it in during development as a failsafe (hence the 'for now' comment). It can hopefully be removed without ill effect. :+1:

@lawnjelly What's your take on batching support for CPUParticles2D? Is that potentially within scope or totally out of sight assuming you can weight or "feel" the complexity of it.

@lawnjelly What's your take on batching support for CPUParticles2D? Is that potentially within scope or totally out of sight assuming you can weight or "feel" the complexity of it.

Looking in GLES2 at least, the particles I think from memory are rendered with a multimesh, and looks very inefficient with setup and drawcalls per particle. It could probably be done as a single dynamic mesh much easier (and unrelated to) the rest of the batching. However, there may be lots of gotchas relating to the existing particle design - it could either be easy or a can of worms. Haven't looked at the particles in GLES3, they may be better already.
I don't really have time to look at it myself (GLES3 batching and helping write new renderers for 4.x have to take priority). If someone else wants to have a go, go for it, but bear in mind there may be some changes to the rasterizer layout for GLES3 batching. And all this will change for 4.x anyway.
I still have to figure out some stuff about the shader binding versions in GLES3 too that has cropped up with a bug with the GLES3 nvidia workaround that may be relevant to GLES3 batching (the binding and states have to be done slightly differently to GLES2).

Thanks. I was asking about CPU particles in GLES2 because GLES3 has GPU particles, while GLES2 is "limited" to CPU particles which are, as you say, probably suboptimal for the time being.
Since the game we're on is a 2D game using GLES2, it has a bunch of CPU particles and most primitives are left out from batching. Enabling batching produces worse performance results than without it, so vanilla GLES2 is best for us. GLES3 also performs worse than GLES2 despite the GPU particles - much more stutter and performance variance. Profiling shows the usual GPU bottlenecks, most probably at the CPU/GPU interface level, since the GPU load itself is relatively low. That said, it looks to me like there are 2 ways of addressing this: a) lower the load on the CPU/GPU sync points = batching, b) move most of those CPU particles to shaders = back to assembly language. There may be other solutions as well but not on top of my hat.
In short, great fun ahaid.


remove upstream dependencies that have no outputs

This resolves the bug reported in https://github.com/NVIDIA-Merlin/NVTabular/issues/1632
The issue was that we were successfully removing parents when calling remove_inputs but the node still showed up in the dependencies of the downstream nodes. We add logic to remove any dependency that does not have an output_schema.
I'll try adding a regression test as well.

LGTM once it has a test

I just noticed this PR - after I had already submitted a fix of my own https://github.com/NVIDIA-Merlin/core/pull/108  =(

@benfred @nv-alaiacano @karlhigley I would like to thank you all for this super timely fix! 🙂


New drivers

Are you open to new driver ?
Tidb is one dB I use for global scale.
Tidb kv store.
What I want to do is try to write a driver for tidb kv so I can use it embedded.
Tidb is just SQL postresql wire format. So pretty straight forward.

Hey @gedw99 and thanks for opening this issue.

Are you open to new driver ?

As I answered about the dgraph support in the roadmap issue:

Would there be interest in support for Dgraph?

Currently, we want to focus on our roadmap and don't want to commit to something we don't have the capacity for it (because it means maintaining and supporting a storage-driver we're not using nor have experience with).
However, @alexsn and I just discussed this morning on adding a public interface for pluggable storage-drivers. So, if someone is willing to take and maintain this, I'll be happy to help.

Having said that, if TiDB is PostgreSQL compatible, you can already use it today.

Ok I will try out tidb and report back..
On Mon, 13 Jan 2020, 10:21 Ariel Mashraki<EMAIL_ADDRESS>wrote:

Hey @gedw99 https://github.com/gedw99 and thanks for opening this issue.
Are you open to new driver ?
As I answered about the dgraph support in the roadmap
<#m_-6857377424387255767_46> issue:
Would there be interest in support for Dgraph?
Currently, we want to focus on our roadmap and don't want to commit to
something we don't have the capacity for it (because it means maintaining
and supporting a storage-driver we're not using nor have experience with).
However, @alexsn https://github.com/alexsn and I just discussed this
morning on adding a public interface for pluggable storage-drivers. So, if
someone is willing to take and maintain this, I'll be happy to help.
Having said that, if TiDB is PostgreSQL compatible, you can already use it
today.
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/facebookincubator/ent/issues/281?email_source=notifications&email_token=ANLOXAICW5A3MAN53P5TONDQ5QXC5A5CNFSM4KF5DEQKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEIYAK7I#issuecomment-573572477,
or unsubscribe
https://github.com/notifications/unsubscribe-auth/ANLOXANTCW2KKTTOQ5OLCYTQ5QXC5ANCNFSM4KF5DEQA
.


How to do transaction/commit/rollback on mysql/sqlite3 ?

Hi, is there any document about how to do transaction/commit/rollback on mysql/sqlite3 ?

Good point. Need to write that.
In short: You can
auto tx = start_transaction(db);
// do something
tx.commit(); // or tx.rollback();

If a transaction goes out of scope without commit or rollback being called on it, it will automatically rollback.

thanks

Hi @rbock , if any thing wrong during the transaction, sqlpp11 will throw sqlpp11::exception, correct ?
So my best practice should be like below, correct ?
try {
  auto tx = start_transaction(db);
  tx.commit();
} catch (sqlpp11::exception e) {
  tx.rollback();
}

tx is not defined in the catch block this way.
But as mentioned above, you don't need to call tx.rollback() yourself. It will automatically rollback in the destructor if it is not committed.

Thanks, so I think all I need is something like:
auto tx = sqlpp::start_transaction(db);
// do my select/insert/update
tx.commit();

Thanks for reply


WIP - DEVX-2762 - feat: aio app package command

New feature: aio app package command.
How Has This Been Tested?
ongoing. See steps below.
To install
git clone --branch DEVX-2762 --single-branch https://github.com/adobe/aio-cli-plugin-app.git
cd aio-cli-plugin-app
aio plugins link .
# to see options
aio app package --help

To uninstall
cd aio-cli-plugin-app
aio plugins unlink .

Types of changes

[ ] Bug fix (non-breaking change which fixes an issue)
[X] New feature (non-breaking change which adds functionality)
[ ] Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

[X] I have signed the Adobe Open Source CLA.
[X] My code follows the code style of this project.
[X] My change requires a change to the documentation.
[ ] I have updated the documentation accordingly.
[X] I have read the CONTRIBUTING document.
[ ] I have added tests to cover my changes.
[ ] All new and existing tests passed.

The packaging artifacts folder is named app-package:

This folder needs to be in the app's .gitignore when the app is created.
Modify the .gitignore file in the default app generator in generator-aio-app

Closing: new PR based on this at #650


Explain the extra brew installs for R on macOS

brew install harfbuzz fribidi libgit2 xquartz

Suggest adding a <details> section that explains these: Are they needed for R in general, or is it something particular about opendp? I know that xquartz is needed with the standard R install, because that install also includes tcltk stuff, so X11 compatibility is not surprising, but not sure about the others.

They are all for devtools, which is developer tooling only. The package itself only has a soft dependency on jsonlite.


use scrollHeight instead of offsetHeight

In situations where the container has some CSS applied (max-height: 100%, flexbox properties and so on), the plugin was reading the offsetHeight and, being forced to be the right one, it didn't trimmed the text.
Reading scrollHeight you are reading the effective height that the text is using.

Oh damn I used an old fork 🙄 By the way I think it gives the idea.

In what cases would using scrollHeight give us something different than if we computed the elements outerHeight?

Example:
.wrapper
  height: 50px
  .shave
    max-height: 100%
    overflow: hidden

If you run Shave on this example, it will do nothing, since .shave is already 50px high.

@FezVrasta this is a very insightful point & has caused me to consider the idea of using clientHeight vs offsetHeightpotentially  🙌 .
However, a use case where scrollHeight is needed suggests a scenario where I would not recommend truncation of any sort. It seems the scenario you brought up should be solved with css (a clearfix or allowing the content to define the height of it's container - maybe something like that?). If you submit a codepen in an issue, maybe we can work through your goal with you?
~THANKS! 🍻

Both these cases will fail:
http://codepen.io/FezVrasta/pen/XjwjzE
I'm using a React implementation of Shave I written so I've not problems since I already fixed it on my side. Feel free to fix it on this library as well if you want.
I can't find downsides of the change I suggest, if you find one please let me know, I'm interested.

@FezVrasta Thanks for your insights. ✔
Based on your examples, I'd just update the css. I added notes in the codepen here:
http://codepen.io/yowainwright/pen/VKOPYW
In reference to the codepen notes I added, my 2nd point might be relevant to you:
**Re:** Removing text, even optimally is dom thrashing which is expensive on the browser. In your case, I _think_ your suggestion would lead to more dom thrashing in many cases.

That's why I so much appreciated your initial comment. & will be considering clientHeight. 👌@jakiestfu @pwfisher


JavalinVite as Javalin Plugin

Describe the feature
I have created a plugin similar to JavalinVue which allows users to create Vue Apps using Javalin but with the following benefits:

One Click Production Builds using Maven
Hot reloading, since it uses the Vite development server during development
All NPM packages are supported. This means tailwindcss, typescript support, ...

It would be great if we could include it into Javalin as official frontend plugin
Additional context
NPM install is executed by the extension, so you just need to add the required frontend packages to the package.json file and run Javalin or the production build. Since the extension installs NPM locally, it even works without having any node or NPM installed on your machine.
Of course, the production build does not include the dev server.
If you think it might be interesting, you can check it out here:
https://github.com/ClemensElflein/javalin-vite

We might need to implement some changes to this in order to fit the Javalin project.
The following things come to mind:

Remove Runtime Dependency to Maven (can be resolved by forking the frontend-maven-plugin and removing unused code)
Add examples for other build systems (Maven, Gradle, Bazel)

Im for sure interested in taking the load of managing an NPM codebase off my back sometimes - this looks super neat, but just out of curiosity, can this work with other frameworks?

At the moment it's Javalin and Maven only, since the runtime component is a Javalin Plugin.

I mean does it work with other frontend frameworks - Since its using the npm plugin internally, can it be used for say, React apps or Angular

@ClemensElflein are you still using this ?

Hi @tipsy,
I'm currently not working on a web app, but it worked great for three different projects of mine so far. The next time I'll start working on a web app, I'd use it again. Hopefully it's easy to migrate to newer versions of Javalin - sorry I did not have the time to follow along with the current Javalin changes so I have no idea if the latest version in Git still works with the current Javalin version.

Thanks for the update !

@ClemensElflein It would be great if we could include it into Javalin as official frontend plugin

We have a new org setup now, so we could create a repository: javalin/javalin-vite. Would you like to move your project to there? (you would retain admin rights for the project).

True, but I can't transfer ownership, because of this error:

The transfer ownership button says I need permission to create repos in the target account:

You have to transfer it to @tipsy and then he'll be able to transfer this to the organization :)

I see, done!

@ClemensElflein thanks, you and Eric are now maintainers of https://github.com/javalin/javalin-vite :)


Channel mapping with callback

Is there a way to do channel mapping while using an audio callback instead of a blocking stream?

There are two different kinds of "channel mapping".

The platform-dependent kind in AsioSettings and CoreAudioSettings. Those should always apply, independent of blocking or non-blocking. I don't really have experience with that, please tell me if it doesn't work for you.

The platform-independent mapping argument in play(), rec() and playrec(). This is only available in those 3 functions. This is not very fancy because it simply creates as many channels as the highest channel number and fills the unneeded channels with zeros. This is implemented in Python, which means that you can just implement the same thing in your own code, be it with blocking or non-blocking streams.

Well, my audio callback, it just runs output[:] = data

Can I call output multiple times out send different things to each channel.

It seems like I can

Yes, output is just a NumPy array. You can assign to its content as many times as you want. You can assign all the content once or in parts one after each other. You should just make sure that you have assigned to each element at least once before you reach the end of the callback. If you don't have data for some channels, you should fill them with zeros. If most of your channels are silent, you can do output.fill(0) and afterwards assign only the channels for which you have data.

Assuming you use NumPy (i.e. not the "raw" stream), you can try something like this:
output[:, out_mapping] = data[:, in_mapping]

For example, if you want to record channel 3 and 7, use in_mapping = [2, 6].
If you want to play back on channels 1 and 4, use out_mapping = [0, 3].

index 6 is out of bounds for axis 1 with size 2... how to do with this?

index 6 is out of bounds for axis 1 with size 2... how to do with this?

See my response in https://github.com/spatialaudio/python-sounddevice/issues/362#issuecomment-893304431.


Missing Animation.module.css in the build and published artifact

If you build, the imported ./Animation.module.css CSS by useAnimation.ts is not present in the lib folder, nor in the publish npm package, which break consumer of react-brand, especially the ones using Typescript (had build failure while trying to use a Card component).

This is the error I receive when building:
./node_modules/@primer/react-brand/lib/animation/useAnimation.d.ts:3:20 - error TS2307: Cannot find module './Animation.module.css' or its corresponding type declarations.

3 import styles from './Animation.module.css';
                     ~~~~~~~~~~~~~~~~~~~~~~~~

Found 1 error in ./node_modules/@primer/react-brand/lib/animation/useAnimation.d.ts:3

The type files for css are generated in the src folder but are not exported in the lib folder. If you can provide pointers to fix this, I can look at fixing it.
I think running tcm with a different output path could do it. But as I'm not familiar with that tool, your input would be appreciated.


Loading models using load_model with custom layers

I am having an issue with loading a model via load_model from an hdf5 file. The model contains custom layers, thus I needed to specify a dictionary to make this layer known to keras. But still it errors out with the following trace:
Traceback (most recent call last):
  File "Y:/Documents/Bachelor/ImageModels/weight_plots.py", line 4, in <module>
    model = load_model('AlexNet/checkpoints/checkpoint-05.hdf5', {'LRN2D': LRN2D})
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\models.py", line 240, in load_model
    model = model_from_config(model_config, custom_objects=custom_objects)
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\models.py", line 301, in model_from_config
    return layer_module.deserialize(config, custom_objects=custom_objects)
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\layers\__init__.py", line 46, in deserialize
    printable_module_name='layer')
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\utils\generic_utils.py", line 140, in deserialize_keras_object
    list(custom_objects.items())))
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\engine\topology.py", line 2395, in from_config
    return cls(inputs=input_tensors, outputs=output_tensors, name=name)
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\legacy\interfaces.py", line 88, in wrapper
    return func(*args, **kwargs)
  File "D:\guth\Miniconda\envs\ba_guth\lib\site-packages\keras\engine\topology.py", line 1726, in __init__
    ' times in the model. '
RuntimeError: The name "LRN2D" is used 6 times in the model. All layer names should be unique.

The error appears to arrise from the fact, that the custom layer is used multiple times. Surely, all layers do have different names, ranging from 'lr_n2d_1' to 'lr_n2d_6', each of them beeing a custom LRN2D layer.
I load the model like this, I am a bit unsure if I used the dictionary wrongly here:
model = load_model('AlexNet/checkpoints/checkpoint-05.hdf5', {'LRN2D': LRN2D})
Can anybody point me into the right direction or tell, if this is a bug?

Did you figure this out?

Hi,
I didn't solve it, but found away around. If you still have the model architecture, you can use the file produced by model.save() actually as well with the `model.load_weights()`` function. This does work with custom layers as well.

#https://github.com/fchollet/keras/issues/4871


HDDS-9469. Fix log message in SCMServiceManager#start

What changes were proposed in this pull request?
(Please fill in changes proposed in this fix

Title: Fix log message in SCMServiceManager#start
Description: Corrected log message for SCMServiceManager#start
(https://issues.apache.org/jira/browse/HDDS-9469)

How was this patch tested?
 Only log message modified

Thanks @navinko for the patch.
Note that Title does not need to be repeated in the PR description (sorry if the PR template is a bit misleading).


Stand in Line Challenge - State the format the result should be returned in [Copy]

Challenge Name
Stand in Line (https://www.freecodecamp.com/challenges/stand-in-line)
Issue Description
The exercise instructions do not state how the first element of the array should be returned:

The nextInLine function should then return the element that was removed.

This could lead to confusion as there are multiple ways to extract the first element of the array. For example, if you used spice(0,1), the output appears perfect but fails the unit tests as it is returned as an array rather than an integer.
Browser Information

Browser Name, Version: Chrome, 54
Operating System: Windows 8.1
Mobile, Desktop, or Tablet: Desktop

Screenshot

@tombarton Thanks for the issue.
The return value of Array.prototype.splice() is an array containing the element(s) removed from the original array. Not the element itself.

Return value
An array containing the deleted elements. If only one element is removed, an array of one element is returned. If no elements are removed, an empty array is returned.

The challenge instructions ask you to return the element that was removed, not an array containing the element that was removed.
If you want to use the Array.prototype.splice() method ofr this challenge, you would then need to extract the element inside of the new array created by the splice method.
I hope this clears things up for you.
If you think the challenge instructions could be improved, I am open to suggestions :+1:

Thanks @Bouncey. It's probably my comprehension skills that need to improve!
I think it was the output box that threw me more than anything. It wasn't until I checked the console log that I realised my mistake.


Persistent Peers Injection - Dream API

Assuming there are two groups: Peers that should be marked as persistent, peers that want those persistent peers injected into their persistent_peers list.

Set up Gaia nodes (using Gaia role)
Collect their IPs + public keys on persistent peers based on this

Use gaiad status to get JSON for status info (e.g. ./go/bin/gaiad status --home /home/gaia/.gaiad/)
Parse out just the node ID and listenaddr port
Register as a variable
Use the inventory_hostname for the address (can this be used instead of an IP?)
Register a variable persistent_peer from {{id}}@{{hostname}}:{{p2p_port}}

Inject persistent peers

Iterate through hosts in persistent peers {% for host in groups.persistent_peers %}
Skip own hostname
Get the persistent_peer variable out {{hostvars[host].persistent_peer}}
Do this to get a line of persistent peers (comma separated?)
Generate an ansible_vars.json file similar to gaiad role, by specifying {"config.toml": {"p2p.persistent_peers": {{persistent_peers | json}} }}
Run copy-config-vars.py to inject the variable into the gaia config
Reboot the gaiad or cosmovisor service

Ping @uditvira plz to review

TODO: Check these end to end tests to see how they do persistent peer injection: https://github.com/cosmos/gaia/pull/1253/files

gaiad tendermint show-node-id is helpful
fixing node key guarantees the node id is fixed

https://github.com/hyphacoop/cosmos-ansible/tree/main/examples#start-a-three-node-testnet-from-scratch


Move Orders API OpenAPI 3.0 Spec

Description
This PR creates a new swagger file outlining the API for the new Task Orders GHC Process flow. The swagger definition uses OpenAPI 3.0.
Reviewer Notes
@kimallen has created an API proposal for the new Payment + Invoicing GHC Process flow that also leverages OpenAPI 3.0.
Please note: This is a draft proposal for the client in order to meet a deliverable. This API spec will undoubtedly change.
Code Review Verification Steps
This PR is a proposal and will not be verified.
References

Pivotal story
New GHC Process Flow

Screenshots

The PR has been updated please re-review!


Update crystal version to 1.0

Update crystal version and shard.yml

Thanks for the PR! I think the workflow is failing because the mangadex shard has to be upgraded first. It's maintained by me and I will work on it soon.

Since we will be moving the built-in MangaDex integration to a plugin (WIP in branch feature/plugin-v2), the mangadex shard is no longer needed. I will remove the dependency from dev and then merge this.

By the way, I forgot to edit Dockerfiles for arm architectures..

Thanks for the reminder. Don't worry I will update and test the ARM Dockerfiles myself.

I fixed the workflow and updated the ARM Dockerfiles, but I haven't tested them yet. I will test them on my ARM devices over the weekend and if everything goes well I will then merge this PR :)

@Leeingnyo Thanks for the PR! It's working fine on ARM. I also fixed the "Executing query" problem you mentioned on Gitter. It was logged by crystal-db from https://github.com/crystal-lang/crystal-db/blob/bf5ca75d1ace7e15b00ca03ad21728b8b00cf007/src/db/statement.cr#L145


Can't seem to make a PBKDF{1,2} key derivation instance

* (ironclad:make-kdf 'pbkdf2 :digest :sha512)

debugger invoked on a IRONCLAD:UNSUPPORTED-KDF in thread
#<THREAD "main thread" RUNNING {1001BCE6D3}>:
  PBKDF2 is not a supported key derivation function

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
  0: [ABORT] Exit debugger, returning to top level.

(IRONCLAD:MAKE-KDF PBKDF2 :DIGEST :SHA512 :N 4096 :R 8 :P 2)
0]

My bad, the symbols are in the ironclad package, i.e
(ironclad:make-kdf 'ironclad:pbkdf2 :digest 'ironclad:sha512)