Commit graph

6774 commits

Author SHA1 Message Date
c4b2902dd4 Invocation: provide simplified API to inject fixed parameter values
* ...by defining a parameter-functor to »drop off« a given value
 * ...also add a static sanity check to reject unsuitable parameter-functor \\
   (e.g. for a processing-functor with different or even no parameters)
2024-12-28 21:48:30 +01:00
52d2c47439 Invocation: integrate passing a parameter-functor into the NodeBuilder
This required some ''type massaging'' to construct the proper follow-up builder type;
other than that, all components work together as expected.

This can be demonstrated both in a direct setup and using the builder.
2024-12-26 21:42:32 +01:00
b46e21e24d Invocation: investigate ways to introduce a parameter-functor
While the handling of invocation parameters is now integrated in the node processing,
there is still a gap to close in the Node Builder, which is tricky due to the way
the parameter-functor is now integrated deeply into the setup of the `FeedManifold`;
so the `PortBuilder` is tasked now with implanting a `FeedPrototype` -- which must be
adapted to a ''specific parameter-functor,'' which is only supplied optionally,
as a further build step.

At first this seemed to present a pattern very similar to a ''State Monad'' — and thus
I investigated if encapsulating the build of the prototype into such a State Monad would
simplify the structure of the builder — yet once again, Monads turned out as ''Anti Pattern''
rather: we'd had to ad an extra component, which is superficially generic
but without any tangible relation to patterns of the real world, it would be
rather technical (using lots of composed lambda primitives, which will be condensed
into a single builder function by the compiler / optimiser. But worse still,
this highly complicated setup does not actually solve the problem with N x M
typed contexts — implying that it ''is not actually an abstraction,'' rather just
pretends to be generic.

The benefit of this lengthy design exercise is to understand better the situation
in the builder, which amounts to building up mixed typed context with several
degrees of freedom. It is better to accept this reality and keep it in  plain sight,
i.e. let the builder be explicitly typed from end to end and do not try
to package parts of this selection process behind a virtualisation.
2024-12-26 18:03:08 +01:00
9f348e6944 Invocation: able to build and invoke a simple Render Node (see: #1367)
**This is a Milestone for the Render Engine integration effort**

After various rounds of prototyping and refactoring,
the Render Node builder and invocation code is now able to
 * bind a simple function
 * handle arbitrary input / output and parameter types
 * invoke a Render Node configured with this function
2024-12-24 06:23:55 +01:00
9484ea0b71 Invocation: identify problems with buffer handling
The ''design exercise'' started yesterday ran into a total rodadblock.
And this is a good thing, as this unveils inconsistencies in our memory handling protocols
 * Buffer Provider Protocol
 * Output Slot Protocol
The latter exposes a `BuffHandle`, which should be usable from within the Render Node code
like any other regular buffer handle — which especially would require to ''delegate the lifecycle calls...''

So while this topic does not hinder us right now to proceed with a Node invocation in test setup,
it must be addressed before we're able to deliver data into an actual OutputSlot.

Created #1387 to track this topic...
2024-12-24 03:21:22 +01:00
33c8f1c5b1 Invocation: investigate forwarding an output data block
This investigation started out as solving an already solved problem...
I'll continue this as a design exercise non the less.

__Some explanation__: To achieve the goal of invoking a Node end-to-end,
the gap between the `Port` API, the `ProcNode` API and the `RenderInvocation` must be closed.
This leads to questions of API design: ''what core operation should the `ProcNode` API expose?''
 * is `ProcNode` just a forwarding / delegating container and becoming redundant?
 * or does the API rather move in the direction of an ''Exit Node''?

This leads to the question how the opened `OutputSlot` can be exposed as a `BuffHandle`
to allow to set off the recursive Node invocation. As it turns out, the onerous for this step
lies on the actual `OutputSlot` implementation, since the API and output protocol already requires
to expose a `BuffHandle`. Yet there is no "real" implementation available, just a Mock setup based
on `DiagnosticBufferProvider`, which obviously can just be passed-through.

Which leaves me with mixed feelings. For one it is conveninent to skip this topic for now,
but on the other hand the design of `BufferProvider` does not seem well suited for such an proxying task.
Thus I decided to explore this aspect in the form of a prototyping test....
2024-12-23 02:31:29 +01:00
2068278616 Invocation: resume integration of Node building
After this extended excursion to lift the internals of Node invocation
to the use of structured and typed data (notably the invocation parameters),
the »Playback Vertical Slice« continues to push ahead towards the goal of integration.

The existing code has been re-oriented and some aspects of node invocation have been reworked
in a prototyping effort, which (in part though the aforementioned rework)
is meanwhile on a good path to lead to a consolidated final version.
 * ✔ building a simple Render Node works now with the revamped code
 * 🔁invoking this simple Node ''should be just one step away'' (since all parts are known to work)
 *  the next step would then be to build a Node outfitted with a ''Parameter Functor'', which is the new concept introduced by recent changes
 *  this should then get us at the point to take the hurdle of invoking one of our **Random Test** functions as a Render Node
2024-12-22 19:47:36 +01:00
81ef3c62e9 Invocation: code clean-up and documentation
Remove left-overs from the preceding prototypical implementation,
which is now obliterated by the change to a flexibly configured `FeedManifold`
with structured, typed storage for buffers and for parameter data.

The Render Node invocation sequence, as rearranged and reworked for the »Playback Vertical Slice«, now seems reasonably clear and settled.

Adding extensive documentation to describe the conventions and structures worked out thus far;
moreover, start makeover of old documentation in the !TiddlyWiki to remove concepts obviously obsoleted now...
2024-12-22 07:00:02 +01:00
e46ff7a8a7 Invocation: switch WeavingPattern and Level-1 builder to the reworked FeedManifold
After the complete makeover of the `FeedManifold` structure,
which among other entails a switch from ''buffer arrays'' to tuples
and the ''introduction of a parameter tuple'', this changeset now
switches the „downstream code“ of the builder and node invocation,
relying on an largely identical invocation API.

The partially finished NodeLink_test now **runs as before**
but on top of a drastically more flexible and open infrastructure.

Quite a feat.
2024-12-21 06:24:37 +01:00
0ccc2d0b89 Invocation: complete rework of the FeedManifold
This completes a deep and very challenging series of refactorings
with the goal to introduce support for **Parameters** into the Render invocation code.

A secondary goal was to re-assess the prototype code written thus far
and thereby to establish a standard processing scheme.

With these rearrangements, the `FeedManifold` is poised to act as **central link**
between the Render-Node invocation code and the actual Media-Processing code in a Library Plug-in


Up to this point, the existing code from the Prototype is still compilable, yet broken.
The __next step__ will be to harness the possible simplifications and enable
the actual invocation to work on arbitrary combinations of buffers and parameters,
enabled by the **compile-time use-case classification** now provided by `FeedManifold`
2024-12-20 22:18:04 +01:00
72703f70c9 Invocation: integrate active ''parameter functor''
While basically the `FeedPrototype` could be created directly,
passing both the processing- and the parameter-functor, in practice
a two-step configuration can be expected, since the processing-functor
is built by the Library-Plug-in, while the parameter-functor is then
later added as decoration by the builder.

Thus we need the ability to ''collect configuration'' within the Level-2 builder,
which can be achieved by a ''cross-builder'' mechanic, where we create an adapted builder
from the augmented configuration. A similar approach is also used to add
the configuration of the custom allocator.

Added an extensive demo in the test, playing with several instances
to highlight the point where the parameter-functor is actually invoked.
2024-12-20 07:05:43 +01:00
8923d0f7b5 Invocation: handle default case with disabled ''parameter functor''
Some further tweaks to the logic to allow using the `FeedPrototype` in the default setup,
where ''nothing shall be done with parameters...''

Provide the basic constructors and a type constructor in FeedManifold,
so that it is possible to install a ''processing functor'' into the prototype
and then drop off a copy into each new `FeedManifold`

With this additions, can now **demonstrate simple usage**

__Remark__: using the `DiagnosticBufferProvider` developed several years ago;
Seems to work well; however, when creating a new instance in the next test case,
we get a hard failure when the previous test case did not discard all buffers.
Not sure what to think about that
 * for one, it is good to get an alarm, since actually there should not be any leak
 * but on the other hand, `reset()` does imply IMHO „I want a clean slate“
Adding some code thus to clean out memory blocks marked as used.
When a test wants to check that all memory was released, there are tools to do so.
2024-12-20 01:47:40 +01:00
479ab8cb15 Invocation: decision logic for invoking a ''parameter functor''
Based on the usage concept developed thus far, we rely on a `FeedPrototype`
to generate the actual `FeedManifold` for each invocation — and this is the extension point
where a ''parameter functor'' can be attached.

Notably, such a parameter functor will be configured from a different part of the builder logic
than the underlying processing function, which is adapted by a Library Plug-in.
Parameters on the other hand will be controlled mostly by configuration within the
Session, because the user chooses to use specific settings, e.g. for an effect.
An important extension to this scheme is **Parameter Automation** — which will be
also attached over the extension point designed here.

Since Parameter can be defined in various flavours, there is some concern that we'll end up
with an excessive number of template instantiations. Thus, we'll explicitly create a »loop hole«
by allowing to define the ''parameter functor'' to be a `std::function`.
This would open a secondary possibility: configuring such a function, but leaving it empty,
which would be a further control switch usable by the builder.
2024-12-19 22:35:12 +01:00
07410e14f1 Invocation: now able to pass parameter tuples
This basically completes the reworked implementation of the `FeedManifold`
An important aspect however is now separated out and still remains to be solved:
''how to configure and invoke a Parameter-Functor?''
2024-12-19 19:58:21 +01:00
3a3b7e4dd7 Invocation: develop a plan how to integrate a Parameter functor
This is one remaining tricky detail to be solved.

The underlying difficulty is architectural:
 - the processing functor will be supplied by the Media-Lib-Plug-in
 - while a functor to set parameters and automation will be added from another context

Yet both have to work together, and both together will determine the effective type of the ''Weaving Pattern''
Thus we'll have to get both functors somehow integrated into the Level-2-Builder,
yet we must be able first to pass this builder instance to the Library-Plug-in and then,
in a second step, another part of the Lumiera Builder logic will have to add the Parameter wiring.

The solution I'm proposing is to exploit the observation that in fact the processing functor
is stored as a kind of »Prototype« within the ''Weaving Pattern'' and will be ''copied'' from there
for each individual Render Node invocation. The reasons for this is, we want the optimiser
to see the full instantiation of the library function and thus get maximum leverage;
thus the code doing the actual call must see the functor or lambda to be able to inline it.

This leads to the idea to ''separate'' this »prototype« from the `FeedManifold`;
the latter thereby becomes mostly agnostic of parameter processing.
However, `FeedManifold` must then accept a copy of the parameter values
as constructor argument and pass it into its internal storage.

This forces yet another reorganisation of the class structure.
Basically the storage modules for `FeedManifold` are now prepared within a configuratiton class,
which actually helps to simplify the metaprogramming definitions and keeps the enclosing namespace clean.
2024-12-19 06:07:07 +01:00
488793174f Invocation: can now accept complex buffer arguments
Add a test case with a wild mix of array and tuple.
Yay! the new code works right away...
2024-12-18 22:22:28 +01:00
990e4cbb68 Invocation: simplify and unify type decision logic
Now reaping the benefits of the ambitious refactorings done yesterday.
- Only retaining the basic distinction of the four use cases
- all further adaptation now directly based on the »lifted« types
- can even add quite stringent compile-time sanity checks.

Now the refactoring is on-par with the capabilities of the old downstream code,
which, btw, could be retained in compilable (yet not working) state. But the new
traits logic is already more capable and could accept tuples and arrays as well.

Next major topic to address is to provide the foundation for parameter handling.
2024-12-18 20:50:33 +01:00
d5bbec6519 Invocation: now able to pass simple buffer case
Can now invoke the FeedManifold with
- either only one output buffer pointer
- or an input and output buffer pointer

With the new support tooling developed yesterday,
the decision logic is now stright-forward to express

__NOTE__ there is a known problem with type-handler registration in the `BufferProvider`;
basically all functors with the same signature are treated as ''identical type'',
which does not account for the fact that functors may hold captured data:
in the example here the second buffer is created with the constructor arguments
given to the first one, ignoring all further sets of similar arguments
2024-12-18 17:04:30 +01:00
844aa7f3d7 Invocation: pave a way for more generic processing via ''type-sequence''
Tuples and the ''C++ tuple protocol'' build upon variadic arguments
and are thus rather tedious to handle, especially in this situation here,
where the argument can ''sometimes be a tuple...''

Several years ago I made the observation that processing by explicit ''type sequences''
(Loki-style) is much simpler to handle and easier to lift to a generic level of processing.
Thus I'll attempt now to extract the ''iteration and extraction part'' of the logic into a new helper.

`lib::meta::ElmTypes<TUP>` allows to process all ''tuple-like types'' and generic ''type sequences'' uniformely
and enables to use both styles interchangably (btw, it is quite common to ''abuse'' `std::tuple` as a type sequence).
With this helper, we can now
- build a ''type sequence'' from any ''tuple-like'' object (and vice-versa)
- re-bind (i.e. transfer the template parameters to another template)
- apply some wrapper
- create AND / OR evaluations over the types
2024-12-18 05:55:00 +01:00
cf4bc380b0 Invocation: break-through with generic implementation
This changeset is a sketch how to switch the entire implementation of the ''Invocation Adatper''
over to a generic argument usage scheme. This requires the ability to
 - detect if some argument is actually a ''structured type''
 - investigate components of such a structured type to draw a distinction between »Buffer« and »Parameter«
 - ''lift'' the implementation of simple values to work on tuples
 - provide a way to ''bridge'' from ''tuple-style'' programming to ''array access''

As a building block, we use a new iteration-over-index construct,
based on an idea discussed in https://stackoverflow.com/q/53522781/444796
The trick is to pass a `std::integer_constant` to a λ-generic
2024-12-18 00:38:16 +01:00
23b4a54e79 Metaprogramming: detect structured types
This solution checks only the minimal precondition,
which is that a type supports `std::tuple_size<T>`.

A more complete implementation turns out to be surprisingly complex,
since a direct check likely requires compile-time reflection capabilities
at the level of at least C++23
 - `std::tuple_element<i,T>` typically implements limits checks,
   which interfere with the detection of empty structured types
 - the situation regarding `std::get<i>()` is even more complicated,
   since we might have to probe for ADL-based solutions, or member templates

The check for minimal necessary precondition however allows us to
single out std::tuple, std::array and our own structured types in
compilation branching, which suffices to fulfils actual needs.
2024-12-17 16:59:02 +01:00
03b17c78da Buffer-Provider: investigate Problem with embedded type-constructor-arguments
This is a possible extension which frequently comes up again during the design of the Engine.
Basically, the `TypeHandler` in the metadata-descriptor used by the `BufferProvder` could capture
additional context-arguments, which are then later passed to an object instance embedded into the buffer.

Yesterday I attempted to use this feature for a simple demonstration in `NodeBasic_test`,
just to find out that passing additional constructor arguments to the capture fails with
a confusing compilation error message. This failure could be traced down to the function binder;
and what at first sight seemed to be a compiler error, turned out to be a quite logical limitation:
When we »close« some objects of the constructor, but delay the construction itself, we'll have to
store a copy in the constructor-λ. And this implies, that we'll have to change the types
used for instantiation of the compiler, so that the construction-function can be invoked
by passing references from the captured copy of the additional arguments.

When naively passing those forwarded arguments into the std::bind()-call,
the resulting functor will fail at instantiation, when the compiler attempts
to generate the function-call `operator()`

see: https://stackoverflow.com/q/30968573/444796
2024-12-17 00:09:18 +01:00
39fee624a9 Invocation: add flexible scheme for storage based on use case
We have now a roughly complete classification of possible use cases.
The invocation can only produce output, process input to output,
and can optionally also accept parameters.

Moreover, each of these cases can require an arbitrary number of actual arguments.
To support all these drastically different case by a common scheme,
`FeedManifold` now uses a »storage slice« for output, input and parameters,
which can be configured at compile time.

TODO: there is an unresolved bug in the test-helper code for the `DiagnosticHeapBlockProvider`,
which prevents us to embed constructor arguments into a buffer descriptor
2024-12-16 02:32:48 +01:00
a477c5953b Invocation: expand capabilities in existing code
This is an attempt to rework gradually while keeping the existing code valid.
For the simple reason that the existing code is quite elaborate and difficult to re-orient.

Thus using a ''second branch,'' and sharing the traits template while expanding its capabilities
2024-12-15 23:25:01 +01:00
1f265044e5 Invocation: further rearrange and rework FeedManifold
What I'm about to do amounts to a massive generalisation, which is tricky.
Instead of having a fixed array-style layout, we want to accept arbitrary and mixed arguments.
Notably, we want to give the ''actual Library Plug-in'' a lot of leeway for binding:
- optionally, the library might want to require **Parameters** (which is the reason for this change)
- moreover, accepting input-buffers shall now be optional, since many generation functions do not need them
- and on top of all this, we want to accept an arbitrary mix of types for each kind.

So conceptually we are switching from C-style arrays to tuples with full type safety

''this going to become quite nasty and technical, I'm afraid...''
2024-12-15 19:02:04 +01:00
40d088c62f Invocation: reconsider how layout of the FeedManifold is established
This is a first step towards the goal to introduce a ''parameter tuple'' into the `FeedManifold`.
Doing so invalidates some of the previously taken decisions regarding the `FeedManifold`;
at that time I was still under the impression of the old design from 2012, which called for a ''Buffer Table''.
Now we are forced to allow for more leeway in the function definition; even more so, since the limitation
to one single input and output Buffer type can be deemed unrealistic anyway.
So why sticking to an array at all? ''Buffers could also be a tuple...''

Seemingly another reason why I used an array was the idea to somehow limit the number of template instances,
by grouping them into a few number of array sizes, like 1,2,5 and 10.
This idea falls short, since in reality it can not be avoided to have the processing function on the type signature anyway.
Thus, the only point where the number of templates could be limited lies in the library plug-in,
where this »processing function« is actually defined as an adapter.
2024-12-14 22:49:57 +01:00
991f0a31f4 Invocation: this »weaving-pattern« evolves into a default
Starting from a prototypical implementation,
where each »slot« in the function is directly connected to the corresponding lead / port,
the implementation of the `SimpleWeavingPattern` (as it was called previously) could be
augmented and adapted gradually — and seems well suited to cover most standard cases of ''media processing''

So a name change is mandated, and the code is also extracted and relocated, possibly even
to be combined with the code of the `InvocationAdapter`, thereby hopefully making the implementation more accessible
Generally speaking, ''weaving patterns'' take on the role of the prime extension point regarding `Port` implementation.
2024-12-14 05:57:37 +01:00
42af5bc4e7 Invocation: rearrange code and cut ties to obsolete implementation draft
The latest phase of conception and planning moved this integration effort a big step ahead.
It is now **basically settled how the invocation works** from top-down.

Thus a lot of ties to ''obsoleted pieces of implementation code'' from the first draft from 2009 / 2012 can be severed now.
 * instead of a `StateProxy` most state management has been broken down into implementation parts
 * instead of orchestrating generic invocation building blocks we will parametrise »weaving-patterns«
2024-12-13 05:13:51 +01:00
fea2bfde7a Invocation: complete helper for chained inline tuples
- complete documentation
- add extensive test coverage for use of the accessors
- demonstrate a more contrieved example, including the dangers
2024-12-12 23:27:10 +01:00
e6403cbc7e Invocation: get structural bindings to work
It seemed like we're doomed...
Yet we barely escaped our horrid fate, because the C++ structured bindings happen to look also for get<i> member functions!

Any other solution involving a free function `get<i>(h)` would not work, since the `std::tuple` used as base class would inevitably drag in std::get via ADL
Obviously, the other remedy would be to turn the `StorageFrame` into a member; yet doing so is not desirable, as makes the actual storage layout more obscure (and also more brittle)
2024-12-12 19:03:43 +01:00
41a6e93057 Invocation: clarify cause of problems
Actually it is the implementation of `std::get` from our STL implementation
which causes the problems; our new custom implementation works as intended an
would also be picked by the compiler's overload resolution. But unfortunately,
the bounds checking assertion built into std::tuple_element<I,T> triggers
immediately when instantiated with out-of-bounds argument, which happens
during the preparation of overload resolution, even while the compiler
would pick another implementation in the following routine.

So we're out of luck and need to find a workaround...
2024-12-12 16:22:04 +01:00
4a7e1eeb36 Invocation: problems with function template overload resolution
Why is our specialisation of `std::get` not picked up by the compiler?

 * it must somehow be related to the fact that `std::tuple` itself is a base class of lib::HeteroData
 * if we remove this inheritance relation, our specialisation is used by the compiler and works as intended
 * however, this strange behaviour can not be reproduced in a simple synthetic setup

It must be some further subtlety which marks the tuple case as preferrable
2024-12-12 04:38:55 +01:00
f2f321a3b8 Invocation: attempt to rely on the C++ ''tuple protocol''
Seems like low hanging fruit and would especially allow to use
those storage blocks with ''structural bindings''

Providing the necessary specialisations for `std::get` however turns out to be difficult;
the compiler insists on picking the direct tuple specialisation, since std::tuple is a
protected base class; yet still surprising -- I was under the impression
that the direct overload should be the closest match
2024-12-11 21:01:25 +01:00
22f4b9dd7e Invocation: implement the chaining and linking functionality
This basically solves this implementation challenge:
It was possible to construct a ''compile-time type-safe'' overlay,
while using force-casts ''without any metadata'' at runtime.

Obviously this is a dangerous setup, but ''should be resonably safe'' when used within the defined scheme...
2024-12-11 03:36:41 +01:00
eed0f55f83 Invocation: rearrange (and fix) front-End constructor
* now yields an instance of the full `HeteroData<X,X,Z>` template
 * work around problems with std::tuple_element_t for derived classes

Can now default-create and direct-init a front-End data block,
access and modify its elements — and the API looks ok-ish for me
2024-12-10 23:23:41 +01:00
510c39091d Invocation: define entrance point for the first data tuple
Decision to use the generic case as short-hand for the first data block,
and thus ''hide the more technical Loki-List specialisations''

With that, I'm finally able to write the first test case...
2024-12-10 19:40:45 +01:00
56bf5ecc8e Invocation: implementation for the chain-constructor
This was a tough nut to crack, but recalling the actual usage situation was helpful
 * the ''constructor type'' must be created / picked-up beforehand
 * we are about to build a ''parameter-computation node''
 * so this constructor presumably is passed to a type parameter of a specific weaving pattern
 * the constructor must be invoked directly to drop-off the new data frame into the local scope
 * it is preferable to attach it only in a second step to the existing HeteroData-Chain (residing in `TurnoutSystem`)

What would be ''desirable'' though is to have some additional safeguard in the type system
to prevent attaching the newly constructed block to a chain with a non-fitting layout,
i.e. the case when several constructors or types get mixed up (because without any further
safe-guard this would lead to uncoordinated out-of-bounds memory access)
2024-12-10 18:49:06 +01:00
54dc8cc032 Invocation: draft accessor and constructor scheme
- the Accessor is pretty much obvious: it carries the type from the enclosing scope and delegates to the generic accessor there
- the Constructor however is much more challenging, because it must construct the chained type ahead, and prepare a constructor functor that can be applied ''later'' to the actual data chain
2024-12-10 01:38:00 +01:00
bc6b69ce71 Invocation: draft a library helper for chained inline tuples
The idea is to build an intrusive linked list of »storage frames«, each of which holds a tuple of arbitrarily typed values.

For such a compound, the C++ »tuple protocol« can be implemented, recursively, serving as base for all actual data access...
2024-12-10 04:14:37 +01:00
8069c874f1 Invocation: develop a concept for handling parameter data
...as part of the rendering process, executed on top of the
low-level-model (Render Node network) as conceived thus far.

Parameter handling could be ''encoded'' into render nodes altogether,
or, at the other extreme, an explicit parameter handling could be specified
as part of the Render Node execution. As both extremes will lead to some
unfavourable consequences, I am aiming at a middle ground: largely, the
''automation computation'' will be encoded and hidden within the network,
implying that this topic remains to be addressed as part of defining
the Builder semantics and implementation. Yet in part the required
processing structure can be foreseen at an abstract level, and thus
the essential primitive operations are specified explicitly as part
of the Render Node definition. Notably the ''standard Weaving Pattern''
will include a ''parameter tuple'' into each `FeedManifold` and require
a binding function, which accepts this tuple as first argument.

Moreover — at implementation level, a library facility must be provided
to support handling of ''arbitrary heterogeneous data values'' embedded
directly into stack frame memory, together with a type-safe compile-time
overlay, which allows the builder to embed specific ''accessor handles''
into functor bindings, even while the actual storage location is not
yet known at that time (obviously, as being located on the stack).

__Note__: a recurring topic is how to return descriptor objects from builder functions; for this purpose, I am adjusting the semantics of `lib/nocopy.hpp` to be more specific...
2024-12-09 22:10:11 +01:00
9393942366 Invocation: Analysis pertaining to storage for param data
During Render Node invocation, automation parameter data must be maintained.
For the simple standard path, this just implies to store the ''absolute nominal Time''
directly in the invoking stack frame and let some parameter adaptors do the translation.
However, it is conceivable to have much more elaborate translation functions,
and thus we must be prepared to handle an arbitrary number of parameter slots,
where each slot has arbitrary storage requirements.

The conclusion is to start with an intrusive linked list of overflow buckets.
2024-12-07 18:15:44 +01:00
544075d143 Invocation: rearrange the Render Node development tests
This is an attempt to take aim at the next step,
which is to fill in the missing part for an actual node invocation...

''...still fighting to get ahead, due to complexity of involced concerns...''
2024-12-07 02:17:55 +01:00
907fbef1ad Invocation: establish a concept how to handle parameter data
This was an extended digression into architecture planning,
which became necessary in order to suitably map out the role
for the `TurnoutSystem` — which can now be defined as ''mediator''
to connect and forward control- and parameter data while specific
render invocation proceeds through the render node network.
2024-12-06 00:16:04 +01:00
d80966c1fb Invocation: draft a scheme how to provide dummy-operations
After the actual processing functions are defined,
the "next level" of test framework building is to find a way
how these bare bone operations can be used easily from a test
with the goal to ''build and invoke a Render-Node''
 * we need some descriptor
 * the bare bone operation must be packaged into an ''Invocation-Adapter''
 * we need some means to configure variants of the setup
2024-11-29 05:42:19 +01:00
ec0c14e129 Invocation: develop more complex text data manipulations
The overall goal is eventually to arrive at something akin to a ''»Dummy Media-processing Library«''
 * this will offer some „Functionality“
 * it will work on different ''kinds'' or ''flavours'' of data
 * it should provide operations that can be packaged into ''Nodes''

However — at the moment I have no clue how to get there...
And thus I'll start out with some rather obvious basic data manipulation functions,
and then try to give them meaningful names and descriptors. This in turn
will allow to build some multi-step processing netwaorks — which actually
is the near-term goal for the ''main effort'' (which is after all, to get
the Render Node code into some sufficient state of completion)...
2024-11-28 04:17:01 +01:00
3bdb5b9dd6 Invocation: implement and test "mixing" of dummy-frames
Bugfix: should use the full bit-range for randomised data in `TestFrame`
Bugfix: prevent division by zero for approximate floatingpoint equality

...and use the new zip()-itertor to simplify the loops
2024-11-27 15:31:50 +01:00
99c4663719 Library: simplify state-core wrapper parameters
As follow-up from the preceding refactorings,
it is now possible to drastically simplify several type signatures.
Generally speaking, iterator pipelines can now pass-through the result type,
and thus it is no longer necessary to handle this result type explicitly

In the case of `IterStateWrapper`, the result type parameter was retained,
but moved to the second position and defaulted; sometimes it can be relevant
to force a specific type; this is especially useful when defining an
`iterator` and a `const_iterator` based on the same »state-core«
2024-11-26 23:22:46 +01:00
b6ade2c0cf Library: further test and documentation of tuple-zipping 2024-11-26 17:35:05 +01:00
252c735b7b Library: solve forwarding of child-expansion
For sake of completeness, since the `IterExplorer` supports building extended
search- and evaluation patterns, a tuple-zipping adapter can be expected
to handle these extended usages transparently.

While the idea is simple, making this actually happen had several ramifications
and required to introduce additional flexibility within the adaptor-framework
to cope better with those cases were some iterator must return a value, not a ref.
In the end, this could be solved with a bit of metaprogramming based on `std::common_type`

...and indeed, this is all quite nasty stuff — in hindsight, my initial intuition
to shy away from this topic was spot-on....
2024-11-26 03:01:28 +01:00
a683e689f0 Library: handle chaining of iterator-pipelines
This involves some quite tricky changes in the way types are composed to form an iterator-pipeline.
Some wrappers are added as adaptors or for additional safety-checks, and to provide a builder-API.
Unfortunately, when building a new `IterExplorer` iterator pipeline from an existing pipeline naively,
composing all those types will add several unecessary intermediary wrapper-layers.
Worse even, the handling of `BaseAdapter` prevents the new tuple-zipping iterator
actually to pass-through any `expandChildren()` call.

These issues are a consequence of using templated types, instead of fixed types with an interface;
we can not just determine if some wrapper is present — unless the wrapper itself ''helps by exposing a tag.''
Even while I must admit that the whole packaging and adaptation machinery of `IterExplorer`
looks dangerously complex already, using dedicated type tags for this single purpose
seems like a tenable soulution.
2024-11-24 23:53:38 +01:00