summaryrefslogtreecommitdiff
path: root/src/modules
AgeCommit message (Collapse)Author
2023-06-16modules/moire: lose unnecessary branch in inner loopVito Caputo
I had benchmarked this change and it showed no difference at all on my 2c/4c i7 X230. But having just tried it on an RPi4B where it moved the test case from 54FPS to 60FPS, a +10% improvement, it's worth the readability loss. It's interesting how Intel's cleverness discourages optimizing in ways that benefit probably *all* the competition... even when the optimization is such a minor change in terms of effort.
2023-06-16modules/moire: some simple optimizationsVito Caputo
Major gain comes from eliminating the cosf() from the inner loop... There's still a bunch left on the table for moire but even just these changes turn 19FPS into 81FPS over here for: '--module=compose,layers=moire\\\,centers\\\=2\,moire\\\,centers\\\=2\,moire\\\,centers\\\=2\,moire\\\,centers\\\=2,texture=none' '--video=mem,size=1366x768'
2023-06-15modules/rkt: drop vestigial TODO comment about handlesVito Caputo
This was written when module names were going to have an @/path/to/context "handle" syntax. But instead I went the "ref" builtin module route, with path=/path/to/context as a setting. While it's more verbose in the settings, it "just works" everywhere that can take a module+settings because the ref builtin is just another module like any other. So this TODO is referring to something that won't happen in a "ref" builtin world.
2023-06-15modules/rkt: end the stream on scene 99999Vito Caputo
This conditionally will end the stream on scene 99999 if connect=off (playback mode) When connect=on it'll just make it show an "EXIT SCENE" diagnostic instead of the "NO SCENE" message. Now you just stick 99999 in the rkt:scene track to end the show. It's assumed 99999 scenes will never be needed...
2023-06-15modules/stars: quick n dirty ticks-based dt scaling of movementVito Caputo
This probably needs more work... it seems wrong to be bypassing the taps altogether when dt is 0
2023-06-15til_module_context: s/ticks/last_ticks/ in contextVito Caputo
And just maintain it as the last ticks value after rendering with the context... A couple modules were already doing this manually in an ad-hoc fashion, just make it a general thing. Updated those modules to reflect the new situation Especially in a rkt world with modules::mixer doing fades, it becomes common to render the same context twice in the same frame for the blending. We need to prevent accelerated animations in such situations. For now let's just rely on ticks in a delta-T fashion to prevent animating the context when ticks is the same. modules::stars in particular needs this fixed up, upcoming commit
2023-06-15modules/mixer: update taps @ context create tooVito Caputo
This moves the tap updating to a function shared by rendering and context create... so we can have a valid externally-driven tap value before rendering a single frame if possible. (this is important for not having spurious frames/flickers in rkt sequences)
2023-06-15modules/rkt: handle stream taps @ context createVito Caputo
It's problematic getting this stuff online at render time, because the modules end up rendering with uninitialized tap values in that first frame. With this change modules can get their taps on-stream at context create, and we'll notice and do the initial rocket update just before returning the rkt context to prime everyone on-stream.
2023-06-14modules/mixer: mildly optimize the faderVito Caputo
This really needs SIMD to fly on-cpu, but this improves things some. Using `--module=mixer,style=fade,a_module=roto,b_module=roto\ --video=mem,size=1366x768 --defaults --go` to test: Before FPS: 92-95 floating mostly around 94-95 After FPS: 107-111 floating mostly around 108-109 so +14.8% FPS (2c/4t i7 X230)
2023-06-14modules/mixer: update T tap once in prepare_frameVito Caputo
It's problematic/racy to always be dereferencing the tap pointer to access it's current value. Running checkers:fill_module=mixer on a 2c/4t (n_cpus=4) machine was quite effective at crashing in mixer::render_fragment() due to dereferencing a NULL snapshot fragment. The "tween" T value is being used to indicate when interpolation of the snapshots is necessary. But repeatedly re-reading the T value via the tap pointer would race with the driving tap. In the case of checkers, which is a threaded module, the mixer contexts are all rendering in parallel at the same path so they're sharing a single pipe for their T taps. This situation of sets of contexts sharing a single path, resulting in their taps all landing on a single pipe, is still largely up in the air and might be actively prevented in the future. But until then, it can be made far less crashy and problematic by just being more careful about dereferencing the tap to access its latest value just once at the prepare frame stage, storing it in the local T variable in the context. Then all the render_fragment() accesses can at least find a stable value in the context from prepare-to-render, so at least the snapshots are there when they should be according to the T value etc. Something like this will probably need to be done regardless of what happens with the context sets sharing the same path. Since when a given tap isn't the driver, it still has to take care to just grab the updated value once for the frame... The tap API can't really automagically do that single update of the local variable when passenger though, since it's been deliberately kept devoid of all the type-specific accessor junk (ptr/elems etc are all void **/void* in the tap api side). Hence why this commit is just ad-hoc updating the local variable in the else branch; it's best positioned to do so directly. But there still needs to be more consideration for thread-safety.
2023-06-14modules/roto: trivial simplification of render loopVito Caputo
Maybe earlier versions used the absolute coordinates in the frame, but the current code doesn't make use of this and simply needs to confine itself into the WxH of the fragment.
2023-06-13modules/mixer: add a fade style, make defaultVito Caputo
This is not optimized at all and tends to hurt the FPS significantly. This is one of those things that would hugely benefit from SIMD, but even without SIMD it could be done better. I just slapped together something obvious for now, as I'd like to focus more on the rkt side but need a better fader for scene transitions than style=flicker. Also changed {a,b}_module= preferred values to blank,compose so you see something happen if you just run --defaults. Otherwise, the compose,compose would just fade between two identical compositions invisibly.
2023-06-13modules/mixer: replace inputs= with {a,b}_module=Vito Caputo
Originally I was thinking a variadic inputs= like compose::layers would be desirable, with the T value's integer serving as an index into the inputs, and the fraction between the integers as the mixing T. But I changed my mind and am instead constraining mixer explicitly to two distinctly named modules; a_module= and b_module= with the T value 0-1 mapping to a-b.
2023-06-13modules/checkers: return -EINVAL on invalid module nameVito Caputo
Not sure why this was -ENOMEM, module lookups don't allocate anything...
2023-06-13*: smattering of random small fixes to silence -WallVito Caputo
I thought the build was already using -Wall but that seems to not be the case, maybe got lost somewhere along the line or messed up in configure.ac After forcing a build with -Wall -Werror, these showed up. Fixed up in the obvious way, nothing too scary.
2023-06-13modules/checkers: introduce clear=,clear_color= settingsVito Caputo
Similar to fill= and fill_color=, these influence how to treat the "clear" cells. Until now "clear" cells would unconditionally just be cleared via til_fb_fragment_clear(). Now they can also be filled w/color,sampled,textured, and maybe in the future a clear_module= will also be introduced. Note that for now I've left the clear_color randomizer disabled, see code comments. Having this setting also makes me wonder if the "filled" cells should be optionally cleared using the "clear" setting first. Imagine a scenario where you have fill_module=shapes, and you want the color around the shape to match the clear color, for instance... Especially once you can pass a color down to the fill_module, controlling these things becomes more critical. There's definitely more work to do here.
2023-06-13modules/checkers: prefix fill_ to fill color+flagsVito Caputo
Preparatory commit for introducing equivalents for the "clear" cells. This renamed the color= setting to fill_color=, in addition to the internal naming.
2023-06-12modules/rtv: gc module contexts on channel switchVito Caputo
This probably needs more work, but this at a minimum should prevent us from leaking contexts in the stream at the myriad paths we construct them at. Context registration replaces what's at the existing path, but rtv produces all sorts of setup paths, and I haven't added any explicit unregistration of contexts at this time. That might change, but for now let's just use this gc mechanism even if it's a temporary hack.
2023-06-11modules/mixer: add rudimentary mixer meta moduleVito Caputo
this is very early/unfinished, hence experimental flag
2023-06-11modules/compose: destroy_context() can't get passed NULLVito Caputo
The modules don't have to defend against this, vestigial from simpler times
2023-06-09modules/compose: remove some vestigial junkVito Caputo
compose must have been derived from rtv originally, which uses txt.h.
2023-06-08modules/rkt: drop vestigial module_setupVito Caputo
a390e82 stopped using this, but didn't remove it. As it was initialized to NULL, it was deffectively all a NOOP.
2023-06-08modules/rkt: detect errors when creating scene contextsVito Caputo
The return value was just being ignored previously, and that really starts mattering in a world with contexts finding others by user-supplied paths making such failures far more likely.
2023-06-06modules/compose: remove vestigial TODO commentsVito Caputo
These are already reality as of late
2023-06-05modules/checkers: use til_module_create_contexts() for fill_moduleVito Caputo
Just a boring replacement of the ad-hoc n_cpus context creates for the fill_module contexts with the newly added libtil equivalent function. Future commits will expand the libtil side to get module contexts registered for discovery purposes on-stream. This change moves a bit closer towards that goal...
2023-06-03modules/rtv: plug non-snow-channel til_setup_t leakVito Caputo
Somewhere along the line this leak was created, there's been a lot of activity surrounding this stuff so it's unsurprising. A little janky surrounding the conditional on snow module, but that's just how snow is handled today - it doesn't get randomized like the other channels do.
2023-06-03til,modules/rtv: supply settings to til_module_setup_randomize()Vito Caputo
Rather than creating an orphaned settings instance private to til_module_setup_randomize(), the function now requires the settings instance be provided. The one remaining caller of this function is modules::rtv. Now that rtv is responsible for creating the settings beforehand, and the settings may be created with a path prefix, rtv gets its til_module_context_t->setup.path prefixed for all the channel settings. Another improvement is now the channel settings instance gets created from the module name as the settings string. So while it's not yet possible to sparsely specify settings with others being randomized, at least now when log_channels=on is in effect, the printed args include the top-level channel module. Having proper complete paths for the rtv channel modules is especially visible in --print-paths output FYI. An interesting test for exercising all this is: ``` $ src/rototiller --module=rtv,duration=0,context_duration=0,snow_module=none,channels=all,log_channels=on --print-pipes --defaults --go 2>/tmp/channels in another terminal: $ tail -F /tmp/channels ``` watch the chaos unfold
2023-06-03modules/montage: introduce tiles= setting, stop randomizingVito Caputo
Montage would randomize orphaned setting instances for the participating modules @ context create time. This not only produced montage tiles one couldn't configure via settings even if they wanted to, but it also produced partial paths due to the orphaned settings instances. With this commit montage tiles are configurable in the same way compose::layers are; a comma-separated list of modules with settings accompanying them. Randomizing is no longer performed, but if seen via something like rtv, that randomizer will operate on the regular setup machinery to produce randomized montages. One new ability delivered with tiles= is you can specify the same module repeatedly to produce a tiled display of the same thing. Those instances may have the same or different settings, it's totally controllable. This also opens up the future for more interesting things like shiftng ticks in the montage tiles... imagine showing the same module a few times in each row, but offsetting ticks into the future/past in the columns. For ticks-driven modules, you'd see the future/past frames side by side, like a flipbook effect. This leaves rtv as the only til_module_setup_randomize() caller remaining...
2023-06-03modules/compose: drop redundant til_module_t*Vito Caputo
Once til_module_context_t.module was introduced, this vestigial module member @ compose_layer_t.module became redundant. So here it's dropped in the obvious manner, but the compose_layer_t struct is retained despite only having til_module_context_t* now. This is in anticipation of future additions where compose settings may set per-layer/texture rendering behaviors (think alpha, colors, texturing toggles, etc)
2023-06-01modules/rkt: deprecate seq_module= in favor of scenes=Vito Caputo
This drops the seq_module= setting in favor of a scenes= setting in the same style of compose::layers; a nested settings instance composed of more nested settings instances, one per scene. A nice side-effect of this change is it no longer uses til_module_setup_randomize() at all, which was being used to mix up the seq_module's settings in a pre-nested-settings world. A new Rocket sync track is introduced named "$context_path:scene" for selecting which scene to render. For now all scenes get created @ context create time, and persist for the entire rkt context lifetime. In the future the context lifetimes might become explicitly controllable with separate Rocket tracks used as booleans. This becomes relevant once modules can make use of existing contexts located within the stream at their respective context paths. Something necessary for integrated transitions between scenes using stuff like fade modules which haven't been added yet. With this change you can already enumerate a set of scenes in the rkt settings string, each 100% explicitly configured, and have Rocket track data select which scene to render on the timeline, and manipulate the taps at their scene-specific context-path-derived track names. In addition to the need for modules picking up existing contexts on the stream, rkt probably needs a way to interactively add/remove/modify scenes then spit out the serialized settings string for the current state of the world. As these aren't functionalities provided by GNU Rocket, and it's unclear how receptive upstream GNU Rocket/glrocket maintainers would be to such additions, rkt will likely first add another listener for a strictly scenes-editing client to connect alongside the GNU Rocket stuff. Just something that shows the current scenes table, and provides a way to edit/add/remove rows there, with the changes realized in rkt real-time. Then the Rocket Editor will just continue using the rkt:scene track to numerically index into this scenes table, without the Rocket Editor having any visibility or awareness of what's going on in that table. Probably ok as an initial stab at making demos with this stack.
2023-06-01modules/rkt: use local variable for rkt_setup_t*Vito Caputo
Mechanical change removing some rkt_setup_t* casting verbosity in rkt_create_context()
2023-06-01modules/rkt: use helper for pipe track namesVito Caputo
This eliminates the ad-hoc track_name[] allocation and construction, since the track_name wasn't being used after getting the track anyways. No point wasting the memory on it, and the little helper constructing the name on-stack exists now for another future use @ rkt_create_context().
2023-06-01modules/rkt: variadic warpper for sync_get_track()Vito Caputo
Preparatory commit for adding scenes and a $rkt_setup_path:scene track for selecting them. This will also likely replace the whole track_name allocation/construction in rkt_pipe_t since we don't actually make use of that name after getting the track (except maybe for debugging purposes)
2023-05-30til: s/til_module_randomize_setup/til_module_setup_randomize/Vito Caputo
Mechanical rename just to make this consistent with til_module_setup()/til_module_setup_finalize() I should probably do a cleanup pass throughout the til APIs to standardize on a subject-verb-object or subject-object-verb order... Things have become a little inconsistent organically over time
2023-05-30til,*: pivot to til_setup_t for context pathsVito Caputo
This changes til_setup_t* from optional to required for til_module_context_t creation, while dropping the separate path parameter construction and passing throughout.
2023-05-30modules/*: utilize til_module_setup_finalize()Vito Caputo
This replaces the few ad-hoc til_module_t.setup() setup-baking callers with the new til_module_setup_finalize() which always produces a til_setup_t having an appropriate path, even when there is no til_module_t.setup() method.
2023-05-28til_setup,*: note settings path in til_setup_tVito Caputo
This commit adds passing the settings instance to til_setup_new() which is used for deriving a path for the setup via til_settings_print_path() on the supplied settings. That path gets an allocated copy left in the returned til_setup_t at til_setup_t.path This path will exist for the lifetime of the til_setup_t, to be freed along with the rest of the baked setup instance when the refcount reaches 0. The incoming til_settings_t is only read @ til_setup_new() in constructing the path, no reference is kept. Basically the til_settings_t* is just passed in for convenience reasons, since constructing the path needs memory and may fail, this approach lets the existing til_setup_new() call error handling also capture the path allocation failures as-is turning til_setup_new() into a bit more of a convenience helper. Note that now all code may assume a til_setup_t has a set and valid til_setup_t.path, which should be useful for context creates when a setup is available.
2023-05-28*: use NULL for free() in til_setup_new()Vito Caputo
Commit 7c8086020 switched the til_setup_new() api to support NULL free_func for free(). This mechanical change pivots to that instead of the awkwardly cast free() parameters.
2023-05-28modules/voronoi: make cell color randomization conditionalVito Caputo
When voronoi is overlayed the colors get sampled, so randomizing them is pointless work every frame.
2023-05-27modules/voronoi: threaded calculate_distances()Vito Caputo
This seems to work on my 2c/4t laptop and is certainly faster. But I'm not being careful about using atomics loading/storing the d->cell pointer, which seems problematic. Surprisingly things aren't crashing here despite that, maybe on a non-x86 smp box it'd be a different story.
2023-05-27modules/voronoi: split voronoi_calculate_distances()Vito Caputo
Preparatory commit for doing the voronoi distance calculations in parallel when possible, as part of render_fragment() instead of all in prepare_frame(). Not all of the distance calculation work can easily be threaded, but it should be possible to compute the post-seed distances concurrently within the spatial bounds of the tiled fragment. This commit doesn't actually change anything functionally, as it's just splitting the old voronoi_calculate_distances() into two and calling them both in succession still from voronoi_prepare_frame(). Subsequent commits will work towards making the render_pass() fragment-aware then ultimately moved to voronoi_render_fragment()
2023-05-27modules/voronoi: remove dirty= setting and variantVito Caputo
This variant is kind of a broken hack, and its brokenness becomes more apparent in a threaded voronoi world. So just drop it for now. I am interested in more voronoi variants, but they can't compromise correctness/introduce instabilities or significantly interfere with performance improvements like threaded rendering. The dithered-ish look of dirty=on was an interesting variant though... bummer.
2023-05-27modules/voronoi: constify til_fb_fragment_tVito Caputo
trivial change; voronoi_sample_colors() only reads from the fragment
2023-05-27modules/rtv: desc the snow_module name settingVito Caputo
Like modules/checkers required for fill_module, we need to do the same for for rtv::snow_module. There's more work to do on rtv::channels, but that's still unsettled stuff in terms of settings syntax since rtv randomizes settings. It's desirable to have the rtv settings able to specify which settings to hold constant at a specific value per-channel, leaving everything else for randomizing on channel switch. But there's no syntax for that kind of stuff currently, and it seems like there's a need to communicate during the setup_func dance when we're in a "settings optional because we'll fill them in automatically at time of use later" to the front-end. It's not strictly a front-end issue though - because the back-end setup_func actually controls the forward progress. From the current setup_func's perspective, everything's important to it and must be fulfilled. And we certainly want the setup_func to continue informing the setup process. So it's more like the channel settings being populated via rtv still need to all get populated, rtv just needs a way to add an attribute to mark which settings are static vs. which should get randomized on every use. Perhaps there should just be a special value syntax reserved for saying "random value" and the front-end can apply that, but then a til_module_randomize_setup() could detect that too in a per-setting flag the front-end set. That way the value gets re-randomized, while the ones without that value set get left alone. Yes, I know this isn't the appropriate place for such commentary. But nobody is reading these things anyways on my toy side project.
2023-05-27modules/compose: trivial indentation fixupVito Caputo
2023-05-27modules/rtv: don't use n_cpus=0 for the context createsVito Caputo
This is harmless as long as rtv stays hermetic. But if rtv gets used in a composite scenario in the future by either removing the hermetic flag, or allowing forced overrides, n_cpus=0 will cause the nested module contexts to become threaded on SMP machines. That's problematic if the outer module context is already a threaded render. What's appropriate here is to just propagate the n_cpus down so if an upper layer has already gone threaded, it will be sending down n_cpus=1 to serialize the nested instances. In practice, as-is, this change basically changes nothing, but prepares for a potential future where rtv participates in threaded compositions. Through a lens of "rtv just rejiggers scenes and there settings on a timer from a settings-specified subset of modules and settings" it's arguably useful as just another module. Sometimes you want something to change itself up periodically in say a compose layer. So preparing for this possibility isn't really all that far-fetched/hypothetical.
2023-05-26til_settings: add til_setting_spec_t.as_labelVito Caputo
Currently settings instances get labels from three sources: 1. explicitly labeled by a root-level til_settings_new() call, like main.c::til_settings_new(NULL, "video", args->video); 2. implicitly labeled in a spec.as_nested_settings w/spec.key 3. positionally labeled in a spec.as_nested_settings w/o spec.key But when constructing setting/desc paths, using strictly these settings instance labels as the "directory name path component" equivalent, leaves something to be desired. Take this hypothetical module setting path for example: /module/layers/[0]/viscosity Strictly using settings instance labels as-is, the above is what you'd get for the drizzle::viscosity setting in something like: --module=compose,layers=drizzle Which is really awkward. What's really desired is more like: /module/compose/layers/[0]/drizzle/viscosity Now one way to achieve that is to just create more settings instances to hold these module names as labels and things would Just Work more or less. But that would be rather annoying and heavyweight, when what's _really_ wanted is a way to turn the first entry's value of a given setting instance into a sort of synthetic directory component in the path. So that's what this commit does. When a spec has .as_label specified, it's saying that path construction should treat this setting's value as if it were a label on a settings instance. But it's special cased to only apply to descs hanging off the first entry of a settings instance, as that's the only scenario we're making use of, and it avoids having to do crazy things like search all the entries for specs w/.as_label set. It feels a bit janky but it does achieve what's needed with little pain/churn.
2023-05-26modules/compose: desc the layer and texture module name settingsVito Caputo
Like modules/checkers required for fill_module, we need to do the same for for compose. It's a little more weird in compose since compose::layers is a nested settings full of unnamed nested settings. But compose::texture is analogous to checkers::fill_module.
2023-05-26modules/checkers: desc the fill_module's name settingVito Caputo
The bare-value value_as_nested_settings.entries[0] setting which serves as the name for module lookup is in a sort of no-mans land between checkers and the underlying fill_module's setup. So we have to do this little bit of rigamarole in checkers, being the entity wiring up the nested module. The fill_module's setup_func won't be doing anything to describe the name's setting as it's only interested in its own settings. There will likely be some helpers made later to streamline this process of composing module/settings hierarchies.
2023-05-23modules/rtv: log_channels s/{yes,no}/{on,off}/Vito Caputo
Using on/off for boolean settings is the established convention in rototiller, rtv went rogue here. Just make it consistent Sometimes it feels like this should be more flexible and support 0/1 yes/no true/false on/off by just having "boolean" typed settings. But I think it may actually pay off long-term to be so opinionated here and making serialized settings heirarchies directly hashable/comparable without major normalization steps (nothing beyond say... case normalization).
© All Rights Reserved