whereas I used to be attempting to optimize SDL2 rendering part as a lot as potential, I reached a wall. I attempted to look on the web however I couldn’t discover any answer. So, I need assistance.
Let me clarify the issue. I’ll use pseudo-code for code examples since this downside shouldn’t be language-dependent.
Lets say we’ve got a fundamental program that follows a tree construction like the next:
Fundamental Handler
Element A0
Element A1
...
Element B0
Element B1
...
...
Tree constructions like these are actually good for code modularity since, when adjustments are wanted, I can simply swap parts as an alternative of fixing all the code.
Due to this fact, to render parts, I’ve the next interface:
INTERFACE Renderer
Render( /* SDL renderer */ ) -> error
And so, the primary physique can simply do the next:
PROGRAM fundamental() -> void
MyApp <- new MyApp()
renderer <- /* setup */
WHILE TRUE DO:
/* Deal with Occasions */
err <- MyApp.Render(renderer)
IF err THEN:
PRINT err
BREAK
WAIT /* delay (ms) */
The issue is that, when rendering, the primary physique has to traverse this big tree for every body; thus, slowing all the rendering part.
To resolve this, I up to date the Renderer interface to incorporate a perform that stories whether or not the part has modified for the reason that final rendering step. If it did, render it, in any other case skip it.
INTERFACE Renderer
IsChanged() -> bool
Render( /* SDL renderer */ ) -> error
At first, this sped the rendering part since now it may possibly skip parts that don’t change or are pointless to attract each body.
Nonetheless, this strategy brought about one other subject since, at each body, not solely the primary execution has to traverse this tree one time to verify if any part has modified, however when adjustments happen, the execution has to stroll up the tree till the foundation after which render every thing.
Nevertheless, this created a brand new downside: At each body, not solely the engine should traverse this tree one time to verify whether it is modified, but when it did, it has to stroll again to the foundation and render every thing.
Particularly on parts like this one:
STRUCT ButtonTable IMPLEMENTS Renderer
Checklist buttons
IsChanged() -> bool
/* verify if this has modified */
/* verify if any subcomponent has modified */
FOR EACH button IN this.buttons DO:
IF button.IsChanged() THEN:
RETURN TRUE
RETURN FALSE
Render( /* SDL renderer */ r) -> error
/* render ButtonTable */
FOR EACH button IN this.buttons DO:
err <- button.Render(r)
IF err THEN:
RETURN err
RETURN NONE
I even tried so as to add multi-threading to hurry up processes however often issues get rendered in a unsuitable order (one part earlier than one other one).
Any concepts on tips on how to repair this?
EDIT: Whereas ready for somebody to reply me, I acquired an answer.
We are able to linearize all parts in an array after which, name the Render methodology on them, this removes the tree construction.
pool cmps = {A, B, C, ...}
FOR EACH cmp IN cmps DO:
IF cmp.IsChanged() THEN: cmp.Render()
In fact, it’s potential so as to add an observer sample to the parts to sign change
STRUCT ButtonTable
/* fields */
Checklist observers
Connect()
Sign()
...
Nevertheless, there are nonetheless few points that I’ve to deal with.
For the reason that render part happens each infrequently, if the rendering part causes different “youngsters” parts to alter, thay might be rendered two occasions; thus, wasting your cycles.
Additionally, how is it potential to create an API that provides an phantasm of a tree-like construction when in actuality is that this pool-observer sample?
Like, earlier than we might do
new MyComponent( /* sub parts */)
however with the brand new construction we’ve got to do the next:
mc <- new MyComponent()
mc.Connect( /* sub parts */ )
main_program.Add( /* sub parts */)
```