Age | Commit message (Collapse) | Author |
|
This needs a bit more work, but at least filtering the same-tick
renders avoids the many-movements-per-frame potential when used
as something like a checkers::fill_module
|
|
This needs a bit more work, but at least filtering the same-tick
renders avoids the many-increments-per-frame potential when used
as something like a checkers::fill_module
|
|
This commit makes ops_sin stateful by tracking last_ticks_ms and its
theta angle.
Unfortunately that necessitates serializing ops_sin on the output
path, currently done using a mutex.
See larger comment in ops_sin.c for why this is all necessary.
|
|
It might be worthwhile to support >1 for these, but as-is it
crashes due to assumptions WRT shape size not exceeding frame
dimensions.
This just prevents crashes if someone tries putting a >1 value in
something like a rkt track for scale/pinch_factor.
|
|
First stab at tapping the parameterized stuff in shapes.
|
|
This also makes the pinches-dependent settings always get
initialized, since when tapped if you moved n_pinches from 0 to
non-zero, the pinches-dependent settings would abruptly become
relevant mid-flight. So this ensures they can have some sane
values, in case they haven't also been set via taps when
n_pinches became non-zero.
|
|
Preparatory commit for potential n_pinches=0, sin(0)=0 which
behaves better here where n_pinches=0 should be a noop.
|
|
Threaded rendering was added in 011d4df35
|
|
This was made redundant by til_ticks_now(), and get_ticks() looks
buggy in its usecs arithmetic on top of it.
|
|
There are no users of this, it can come back if needed.
|
|
In the case of clones there's multiple identical contexts at the
same path, putting their taps on the same pipe.
Since these clones likely exist for the purpose of parallel
rendering, chaotically scheduled, it's arbitrary which of the
clones will render first in a given frame. So it would just be a
matter of luck if the first to render was also the driving tap
established at context create time. Until the driving context
rendered, the non-driving contexts would render potentially stale
values from their taps, carried from the last frame. Then the
driving tap's context would render, advancing all taps it drove,
and it plus any subsequent renders sharing the pipe in the frame
would have the new tapped values, producing randomly inconsistent
results.
You can easily cause this today with checkers::fill_module=plato,
since plato has some taps for the orbit/spin rates, and checkers
uses context clones for parallel fill_module= rendering.
Note this is orthogonal to cases like modules/rkt, where hooks
are used to steal ownership of the pipes when they're created.
rkt also becomes the driver of the taps from its ctor hook, since
it bridges Rocket data to the taps, and this commit does
potentially interfere with that by introducing a per-frame
competition to determine driver. But since rkt is the top-level
rendering module when its in use, calling into the per-scene
module contexts when appropriate, it's guaranteed to always win
the race as long as it maintains its taps using Rocket-provided
values before rendering the scene - which is the way it works
today.
|
|
This needs the stream pulled in so the signature changed to
accomodate that.
Also modules/rkt was calling this conditionally which won't be
compatible with the per-frame driver race model, so always call
it to maintain the driving position every frame.
|
|
This is needed for determining which tap's first on a given pipe
per-frame.
|
|
Tell the stream when starting a new frame...
|
|
This adds til_stream_start_frame() which advances a per-stream
counter.
Subsequent commits will make use of this for implementing a
pre-frame competition for pipe ownership.
|
|
Mechanical change of ensuring what little taps are implemented
always get updated @ til_module_t.context_create() time as well
as on every frame.
This ensures the pipes are registered on stream immediately upon
context creation, rather than appearing only once the context
gets rendered the first time.
|
|
Another trivial leak fixup.
|
|
This triggers immediate cleanup of the replaced context.
It's being done after the new context is fully installed as the
replacement, with an eye towards enabling a baton style handoff
of the existing context's owned pipes to the replacement, for
taps they have in common. That's not being done yet, but it'd be
impossible if the gc occurred before creating the replacement,
since the existing context's pipes would already be untapped (and
removed).
|
|
Another trivial leak fixup
|
|
On shutdown til_stream_untap_owner() will call into the pipe_dtor
hook if set. So until now this was just (harmlessly) leaking the
rkt_pipe_t allocated by the pipe_ctor hook on the road to process
exit.
But in the interests of silencing ASAN about leaks on graceful
exit, I'm tying up these loose ends.
This dtor will also be utilized for performing a FORGET_TRACK via
Rocket once that's a thing.
While here I also got rid of the pipe_dtor return value, as it's
unused with no clear potential purpose (for now).
|
|
This is mainly to prevent the mixer's b_module=compose default
from always sending the randomizer down a deep nested compose
scenario.
But it's also just giving the mixer random variety in both a/b
modules, while keeping compose out.
This alone seems to go a long way towards preventing
problematically deep randomized setups under rtv.
|
|
Not bothering with fixing this because rtv needs its channels
setup redone altogether to better resemble something like
rkt::scenes, but allowing partial specification of the settings
as a means of controlling specific settings while randomizing the
rest.
|
|
til_str_appendf() preventing overflows doesn't do much good if we
don't notice the errors and behave appropriately...
|
|
In the wholesale transition to til_module_setup_full() there's
been a lot more problematic randomized setups either extremely
deep or plain infinite.
Due to the primitive escaping mechanism performed by
til_settings_as_arg(), where escape patterns grow exponentially
with depth, it's quite realistic (and observed) for these
problematic setups to exceed SIZE_MAX.
So I'm putting some guard rails in to cap a given til_str_t to
SIZE_MAX. It might make more sense to move the limit well below
SIZE_MAX, but this should at least prevent overflows.
|
|
Typically people do a exponential style growth in such
circumstances, but in my experience that tends to allocate nearly
double what's needed quite often.
Trying just a linearly increasing allocation size that bumps up
the minimum amount every time a resize is triggered. If the
needed amount exceeds the new growth increment, the larger value
is used, but the growth rate still follows the minimum bump.
I expect this to evolve more, just wanted to do something to
speed up til_str a bit from it's naive approach.
|
|
This was prevented before but lost in the shift to
til_module_setup_full() wrappers...
|
|
more cleaning up stuff on exit
|
|
cleanup_channel() is called from rtv_destroy_context(), which
can be called by a gc. The gc isn't reentrant and generally
isn't expecting this, so it breaks in hilarious ways when this
happens, usually ending in a segfault.
gc should probably get some defenses for asserting on reentry...
for now let's just prevent crashing by removing the gc call from
the destroy path.
|
|
b6362c54 introduced shapes_destroy_context() for the radcache,
but didn't actually cleanup the context, oops.
trivial fix
|
|
trivial fix of a trivial leak on teardown
|
|
This gets rid of the rototiller_thread() pthread_cancel() based
exit which seemed to rarely make clang's ASAN
(-fsanitize=address) very angry with a segfault in libc somewhere
Instead of trying to chase that down I'm just getting rid of it,
it's unnecessary.
|
|
This makes it so til_fb_page_get() will return NULL when the fb
has been "halted". If til_fb_page_get() is already waiting for a
page to become available, it will be woken up by til_fb_halt().
Preparatory commit for eliminating the reliance on
pthread_cancel() to terminate rototiller_thread() on shutdown.
Cancellation is always a PITA, especially cross-platform, but in
general it's so easy to have subtle bugs when using it.
|
|
Pages that have been handed out from the inactive list didn't
live on any lists, not until they were submitted.
This commit keeps all pages on a separate list to make cleanup of
outstanding pages in til_fb_free() trivial, which has also been
introduced here.
Just tidying up the shutdown to get rid of a bunch of harmless
leaks, in an effort to make ASAN more useful in detecting real
leaks on graceful exits.
|
|
It's expected that all mondule contexts will have been cleaned up
by the final gc in til_stream_free(). If the gc returns a
non-zero skipped count, it suggests there's a program bug leaking
registered contexts.
|
|
Preparatory commit for making til_stream_free() assert on leaked
module contexts.
|
|
Leaving the larger n_module_contexts on reuse creates the
potential for a NULL ptr dereference in places like gc which
check the refcount of each countext in the set, without testing
for NULL.
Rather than making everything check for NULL, just shrink the
count when it gets reused in a smaller case. This whole reuse
thing is kind of a silly little optimization anyways, and will be
revisited when cloning either happens or the sets become
deprecated.
For now just prevent creating situations that can crash.
|
|
Plug a small leak
|
|
Technically this was leaking contexts but it's only done on the
road to process exit currently anyways.
|
|
Silly bug, these fragmenters need to be revisited in general to
have less copy pasta across the texture fragment and main
fragment.
Easily triggered with:
--seed=0x64daba35 '--module=compose,layers=julia\,checkers\\\,size\\\=:96\\\,pattern\\\=checkered\\\,fill_module\\\=:checkers\\\\\\\,size\\\\\\\=128\\\\\\\,pattern\\\\\\\=checkered\\\\\\\,fill_module\\\\\\\=moire\\\\\\\\\\\\\\\,type\\\\\\\\\\\\\\\=pinwheel\\\\\\\\\\\\\\\,scale\\\\\\\\\\\\\\\=1\\\\\\\\\\\\\\\,pinch\\\\\\\\\\\\\\\=0\\\\\\\\\\\\\\\,points\\\\\\\\\\\\\\\=5\\\\\\\\\\\\\\\,spin\\\\\\\\\\\\\\\=.1\\\\\\\,dynamics\\\\\\\=alternating\\\\\\\,dynamics_rate\\\\\\\=1.0\\\\\\\,fill\\\\\\\=textured\\\\\\\,fill_color\\\\\\\=0xffffff\\\\\\\,clear\\\\\\\=textured\\\\\\\,clear_color\\\\\\\=0x000000\\\,dynamics\\\=alternating\\\,dynamics_rate\\\=1.0\\\,fill\\\=textured\\\,fill_color\\\=0xffffff\\\,clear\\\=textured\\\,clear_color\\\=0x000000,texture=plasma' '--video=sdl,fullscreen=off,size=640x480'
|
|
The existing code wasn't clipping correctly to the right/bottom
edges of the incoming fragment when the xoff/yoff was 0 but
xshift/yshift non-zero. In that case the incoming fragment bound
was unintentionally being enlarged, resulting in an overrun when
the such a cell was filled/cleared.
It was discovered watching montage under rtv, which stumbled
across running checkers w/size=128 on a montage tile of 128x96.
The height/y coords of the single checker cell filling the whole
montage tile weren't getting clamped properly down to the 96-tall
tile.
The shifting for centering checkers introduced some really
annoying arithmetic in this fragmenter.
|
|
Trivial changes to improve some naming / scoping, done while
investigating a bug.
Nothing functionally changed
|
|
This module is here to stay
|
|
Blend is a more accurate word for what's being done.
Fading is something you can achieve with the blend mode, if you
use something like "blank" as one of the modules. But when you
have two modules generating content, it's not a fade, it's just a
blend.
It might make sense in the future to support a "fade" which
assumes a solid color for one module rather than having to use
the "blank" builtin which burns memory bandwidth on a blank
frame.
|
|
Just more largely mechanical changes transitioning ad-hoc nested
module handling over to til_module_setup_full().
|
|
|
|
Now you can seed the scene editing with a top-level serialized
scene in "as_arg" form, just like NEWSCENE.
The current scene being edited is shown in serialized form for
convenient copy & paste into an editor for manipulation, between
the []s both to also show what the default seed will be if you
just press enter. When using the copy & paste w/editor approach,
you'd just paste the tweaked form directly into the waiting
prompt before hitting <enter>.
Regardless of what happens at the initial EDITSCENE prompt, the
current implementation always goes through an interactive
visiting of all the settings. Simply pressing enter at those
individual settings will accept their current value from the
serialized seed, or a default if not present in the settings.
|
|
This doesn't need to be a distinct state since it's basically
just a banner for the start of the newscene process which never
recurs, it's not an interactive prompt or dialog of any kind...
|
|
Running something like:
'--module=checkers,size=64,fill_module=shapes,style=circle --defaults --go'
Would show some artifacts in the top portion of the filled cells
at certain phases of the spining shape. This was introduce by
the radcache, and it's caused by the overhanging tiles on the
perimeter and how their being clipped was carrying into the
radcache contents then used for all subsequent renders.
This commit just makes setting radcache.initialized conditional
on the incoming fragment being a full-frame fragment as a quick
fix. See comment for more info on what to do long-term.
|
|
There's potential for some of the per-cpu fill_module_contexts to
go unused for an entire frame. When this occurs, depending on
the fill_module in use, it can lead to their context's state
diverging.
To mitigate this possibility, add a tidying up pass in
checkers_finish_frame() where such straggler contexts are
identified and forced to render once into a cell-sized waste_fb
of off-screen memory.
This ensures all contexts see all frames/ticks that any
participated in, preserving their clone status across the board.
Prior to this you could see jittering in something like
'--module=checkers,fill_module=roto' as the roto contexts
diverged on the r/rr variables when some didn't get in on the
action of some frames.
See large TODO comment for why this approach is used instead of
something less wasteful of cpu time.
If this approach is kept, it might make sense to do the waste
rendering in parallel. Systems with large numbers of cores could
end up with many stragglers, depending on how many cells there
are vs. cpus. I don't have any such systems so it's difficult to
test any efforts in that vein.
|
|
In compositions where roto recurs in the same frame, it's
wasteful to keep rendering the fill_fb contents manifold for the
same tick. They shouldn't be varying anyways...
It'd be different if the fill_module rendered directly to the
output fragment in an overlay manner, but the current
roto implementation doesn't do that. It's just sampling fill_fb
like a tiled texture sampler would.
The performance hit here is easily observed by doing something
like:
--module='checkers,size=4,fill_module=roto\,fill_module\=moire' --video=mem --defaults --go
Before this change, FPS=1 on my i7 X230. After, FPS=~400.
|