-
-
Notifications
You must be signed in to change notification settings - Fork 293
graphics.undefineEffect() #300
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
…nd buffer and assignment logic Next up, prepare details from graphics.defineEffect()
…from Program Slight redesign of TimeTransform with caching (to synchronize multiple invocations with a frame) and slightly less heavyweight call site
Err, was calling Modulo for sine method, heh That said, time transform seems to work in basic test
Fixed error detection for positive number time transform inputs Relaxed amplitude positivity requirement
Maintenance Revert Test
My mistake adding back changes made
This reverts commit 0b5e1e9.
… smart pointers don't check out
…, but only reified if undefined, this time with the loader rather than prototype Some corresponding logic to ignore the prototype when appropriate
…o could stomp on them if more than one multi-pass effect used another effect that was undefined Commented a few bits
Like I already said, this is brilliant stuff! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Currently, after calling
graphics.defineEffect()
successfully, the effect in question persists while the program does: until close or relaunch. This is almost always perfectly fine.There are some trouble spots, however.
One of them: editing shaders. I've dabbled with something where you link nodes together, à la Blender or Unreal Editor. An in-app take on Shader Playground would be another example. Without being able to replace obsolete ones, new effects (with unique names) will continue to accumulate as we make updates, wasting many CPU- and GPU-side resources. This is especially egregious since an edit might only change a line or two!
@XeduR also mentioned this being relevant to his Solar2D Playground, if one wants to write custom shaders. Since a "true" relaunch never actually occurs, some steps need to be emulated, but this falls flat with permanently registered effects.
The details:
A few concerns needed addressing.
Removing the effect is one thing, but what if an object is still using it? With most effects, this actually "just works", since resources doled out to instances are either cloned or ref-counted.
Multi-pass effects complicate matters. In general, effect resources are only instantiated on demand, when we first assign the effect. With "simple" effects this is straightforward, since the defined one is what we want.
When defining a multi-pass effect, we list several sub-effects by name in
graph.nodes
. Presumably, we want these to be effects that are already defined, or soon will be. That "will be" speaks to the problem: since resources are instantiated lazily, one of these child effects might be undefined and even replaced before the actual multi-pass one is ever brought into being. Simply grabbing whatever goes by a given name is now a matter of uncertainty.To address this, a "stub" system has been introduced. If a multi-pass effect uses any custom shaders, we map a stub table to each name, keeping these in a local list. We also add them to a global list. (If a name is already present in the latter, we instead add the corresponding stub to the local list.) Since both lists see the same table references, the stubs are shared.
If we undefine a child effect, it will see that it has a stub in the global list. It registers its lazy-loader here; the stub being shared, this will show up in the multi-pass effects' local lists. The entry is then evicted from the global list, since it no longer exists to the world at large.
While a multi-pass effect is being instantiated and connecting its child effects, it consults its local stubs. Any lazy-loader found in this way is used instead, so the proper choices are made despite any undefinitions.
This is my test:
I tested with this image, but anything would do, since it was only used to get the fill to generate texture coordinates.
They were getting noisy during testing, but those
print()
s in thegraphics.listEffects()
loops can be uncommented to show everything currently (still) defined. Most of these are Solar's built-ins but you'll also see (or not) the ones written for the sample.I create a first object,
r1
, and assign it an effect,filter.custom.effect
; it sticks around briefly before being removed. In the midst of this,graphics.defineEffect()
is called, butr1
is fine and even performs time-dependent updates.Another "effect1" is then defined and assigned to a new object,
r2
.A multi-pass effect incorporating the original
filter.custom.effect1
is defined early on and then some rounded rects using it are gradually added via a timer. By the time these happen, the old "effect1" has been undefined.A couple more cases may be tested:
If we never assign it to
r1
,filter.custom.effect1
gets undefined before ever being instantiated. In one of the middle commits I had been registering prototypes in the stubs, but this situation will undermine that approach; the lazy-loadersexist immediately after definition, so proved to be the right way to go.
Removing
r1
actually came from an older test: if you comment out the timer that creates the rounded rects, nothing more will reference the originalfilter.custom.effect1
oncer1
is gone, and its GPU resources will soon be cleaned up. (I had someCoronaLog()
s inRtt_GLProgram.cpp
code verifying as much, since removed.)