Skip to content

Replace use of push constants in 2D RD renderer with uniform buffer#80458

Open
SlugFiller wants to merge 1 commit intogodotengine:masterfrom
SlugFiller:2d-push-constant-as-buffer
Open

Replace use of push constants in 2D RD renderer with uniform buffer#80458
SlugFiller wants to merge 1 commit intogodotengine:masterfrom
SlugFiller:2d-push-constant-as-buffer

Conversation

@SlugFiller
Copy link
Copy Markdown
Contributor

This removes the 128 byte limitation on push constant size, by only using the push constant as an index into the generated buffer. This allows adding more per-instance per-draw command data.

@SlugFiller SlugFiller requested a review from a team as a code owner August 9, 2023 20:16
@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch 2 times, most recently from adb6fe1 to bcf46b6 Compare August 9, 2023 20:26
@Calinou Calinou added this to the 4.x milestone Aug 10, 2023
Copy link
Copy Markdown
Member

@AThousandShips AThousandShips Aug 10, 2023

Choose a reason for hiding this comment

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

Suggested change
return; //nothing to do, its the same
return; // Nothing to do, it's the same.

Comment style nitpick, applies to all modified code even if it is just copied or relocated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Also, "its" -> "it's"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//something odd happened
// Something odd happened.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//bind pipeline
// Bind pipeline.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//bind textures
// Bind textures.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//bind pipeline
// Bind pipeline.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//pass collision information
// Pass collision information.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
fb_uniform_set = RID(); // Force the uniform set to be recreated with the new buffer
fb_uniform_set = RID(); // Force the uniform set to be recreated with the new buffer.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
//push constants buffer
// Push constants buffer.

Copy link
Copy Markdown
Member

@AThousandShips AThousandShips Aug 10, 2023

Choose a reason for hiding this comment

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

Suggested change
inline void _prepare_canvas_texture_data(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); //recursive, so regular inline used instead.
inline void _prepare_canvas_texture_data(RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, PushConstant &push_constant, Size2 &r_texpixel_size); // Recursive, so regular inline used instead.

Copy link
Copy Markdown
Member

@AThousandShips AThousandShips Aug 10, 2023

Choose a reason for hiding this comment

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

Suggested change
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, const PushConstant &push_constant); //recursive, so regular inline used instead.
inline void _bind_canvas_texture(RD::DrawListID p_draw_list, RID p_texture, RS::CanvasItemTextureFilter p_base_filter, RS::CanvasItemTextureRepeat p_base_repeat, RID &r_last_texture, const PushConstant &push_constant); // Recursive, so regular inline used instead.

@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch from bcf46b6 to 829bf3f Compare August 10, 2023 19:22
@SlugFiller
Copy link
Copy Markdown
Contributor Author

Fixed comment styling.

P.S. If it's a priority, shouldn't there be a mega-PR fixing comment styling across the entire codebase?

@AThousandShips
Copy link
Copy Markdown
Member

AThousandShips commented Aug 10, 2023

That's why we do it like this, to bring it slowly in line with the correct format, instead of doing a massive PR polluting the blame history, if your code already touches it however it's different, see #80414 (comment)

Copy link
Copy Markdown
Member

@clayjohn clayjohn left a comment

Choose a reason for hiding this comment

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

This is a great start! Have you tested performance at all vs using push constants? I suspect that this approach is around the same speed as the current approach, but it might be slightly slower. At any rate, it is a good start to build off of.

On that note, what are your plans for moving forward with this? Are you going to take a stab at batching next, or are you going to look into per-instance uniforms?

@SlugFiller
Copy link
Copy Markdown
Contributor Author

@clayjohn For now I'm leaving it as is. I'm just creating it as a basis for others. I have other priorities for next features.

If I was doing something extra, it would have been color/modulation separation. But once this is merged, it should be a small enough change that anyone could do it.

@clayjohn
Copy link
Copy Markdown
Member

@clayjohn For now I'm leaving it as is. I'm just creating it as a basis for others. I have other priorities for next features.

If I was doing something extra, it would have been color/modulation separation. But once this is merged, it should be a small enough change that anyone could do it.

I see. I guess I misunderstood the plan for this. As-is, I don't think we should merge this change by itself. Right now it adds complexity to the renderer for no apparent gain. While it is helpful foundational work for other possible features/improvements, I think it is better to leave this PR open for other potential contributors to pick up where you left off

@SlugFiller
Copy link
Copy Markdown
Contributor Author

@clayjohn I suppose it's possible for others to build PRs on top of an unmerged PR. I probably wouldn't. But it's your call. This one isn't really a blocker for me.

Plus, it would be easier for me to rebase this on top of canvas groups rather than the other way around. So I'd rather that one be merged first anyway.

@Calinou
Copy link
Copy Markdown
Member

Calinou commented Aug 11, 2023

As I understand it, this PR makes it possible to address #49781 in the future.

@darksylinc
Copy link
Copy Markdown
Contributor

darksylinc commented Aug 11, 2023

I agree with the author that reading draw_data_buffer.data[draw_data_index.index] all the time instead of simply data makes parsing the code ('parsing' as in mentally parsing and understanding what is going on, I'm not talking about compilers) much harder.

As I just replied on Godot chat, there are two possible ways:

  1. Using #define myStruct draw_data_buffer.data[draw_data_index.index] as he pointed out.
  2. Simply copy by value const MyStruct myStruct = draw_data_buffer.data[draw_data_index.index]

As long as data comes from an UBO, copy by value is free because the shaders, unlike C code, can assume that the pointer is read-only and does not alias (see strict aliasing in C).

That is a bit more complicated if draw_data_buffer is a non-read-only non-restrict SSBO, but that is rare (and usually kills performance regardless of what you do).

If Copy-by-value causes a performance degradation then that's more likely to have to do with glslang compiler not being good enough at optimizing this case, rather than a design/pattern problem.

@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch from 829bf3f to c2f0b8e Compare August 11, 2023 14:59
@SlugFiller
Copy link
Copy Markdown
Contributor Author

@Calinou You understand correctly. That is the main point. It was theoretically possible to address this in a single mega-PR, but it feels like two separate changes to me, so I only created the foundation, leaving the rest for a separate PR.

Another big reason to not make it in a single PR, is that there are multiple possible ways to solve #49781 (building on this PR), with some being potentially breaking. So this PR only does the change that would be common to any such solution, and leaves the bikeshedding for a later date.

I took @darksylinc 's advice and minimized the changes to canvas.glsl. It is a lot more readable now, and isn't as harmful to merges and the blame history.

@QbieShay QbieShay self-requested a review September 13, 2023 12:52
@BastiaanOlij
Copy link
Copy Markdown
Contributor

Approved in principal pending two point discussed during rendering effects:

  • rename to something more appropriate such as PerInstanceBuffer
  • have a use case implemented so it is not just a structural place

@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch from c2f0b8e to 8791849 Compare September 20, 2023 16:25
@SlugFiller
Copy link
Copy Markdown
Contributor Author

Renamed and rebased.

@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch from 8791849 to 323a607 Compare October 6, 2023 11:56
@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch from 323a607 to 959f035 Compare February 2, 2024 00:10
@nikitalita
Copy link
Copy Markdown
Contributor

In my testing with games that have huge amount of sprites on the screen (bullet hell games, like this one), this PR performed slightly faster than current master; around a 4-5% speed-up.

@SlugFiller SlugFiller force-pushed the 2d-push-constant-as-buffer branch from 959f035 to b95e05f Compare March 5, 2024 05:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants