Commit graph

16 commits

Author SHA1 Message Date
43373e11e7 Invocation: prepare mechanism for default input wiring
The intention is to offer an automatic 1:1 association
between the »input parameter slots« of the processing function
and the ''lead nodes,'' thereby always using the same default
port, corresponding to the current port number under construction.

Unfortunately, the preceding refactoring removed the information
necessary for a simple implementation, as the port array is now
built up late, in the final build() function...
2024-10-25 05:10:16 +02:00
0144049f9d Invocation: reconsider data access and allocator usage from Builder
The next step is to round out the first prototypical implementation,
which requires access to ''lead node ports'' and thereby generally
places focus on the interplay of ''data builders'' within the ongoing
build process. While the prototype still uses the fall-back to simple
heap allocation, notably the intended usage will require to wire-through
the connection to a single `AllocationCluster`. This poses some
challenge, since further ''data builders'' will be added step-wise,
implying that this wiring can not be completed at construction time.

Thus it seems indicated to slightly open-up the internal allocator
policy base template used by `lib::SeveralBuilder` to allow for some
kind of ''cross building'' based on a shared compatible base allocator
type, so that the allocation policy wiring can be passed-on from an
existing `SeveralBuilder`
2024-10-23 16:27:09 +02:00
554a64e212 Invocation: solve passing of the function definition
- the chaining constructor is picked reliably when the
  slicing is done by a direct static_cast

- the function definition can be passed reliably in all cases
  after it has been ''decayed,'' which is done here simply by
  taking it by-value. This is adequate, since the function
  definition must be copied / inlined for each invocation.

With these fixes, the simplest test case now for the first time
**runs through without failure**
2024-10-22 05:59:00 +02:00
df37fec500 Invocation: switch WeavingBuilder to produce the result via λ
This change allows to disentangle the usages of `lib::SeveralBuilder`,
so that at any time during the build process only a single instance is
actively populated, all in one row — and thus the required storage can
either be pre-allocated, or dynamically extended and shrinked (when
filling elements into the last `SeveralBuilder` currently activated)

By packaging into a λ-closure, the building of the actual `Port`
implementation objects (≙ `Turnout` instances) is delayed until the
very end of the build process, and then unloaded into yet another
`lib::Several` in one strike. Temporarily, those building functor
objects are „hidden“ in the current stack frame, as a new `NodeBuilder`
instance is dropped off with an adapted type parameter (embedding the
λ-type produced by the last nested `PortBuilder` invocation, while
inheriting from previous ones.

However, defining a special constructor to cause this »chaining«
poses some challenge (regarding overload resolution). Moreover,
since the actual processing function shall be embedded directly
(as opposed to wrapping it into a `std::function`), further problems
can arise when this function is given as a ''function reference''
2024-10-22 03:20:50 +02:00
0de7905444 Invocation: introduce pattern data holder into NodeBuilder
- add an unspecified data holder type into the NodeBuilder
- establish ability to cross-build a `NodeBuilder` with adapted data holder
2024-10-21 04:40:51 +02:00
b4aee6fba8 Invocation: work out solution for a precisely fitting allocation
Conduct in-depth analysis to handle a secondary, implementation-related
(and frankly quite challenging) concern regarding the placement of node
and port connectivity data in memory. The intention is for the low-level
model to use a custom data structure based on `lib::Several`, allowing for
flexible and compact arrangement of the connectivity descriptors within
tiled memory blocks, which can then later be discarded in bulk, whenever
a segment of the render graph is superseded. Yet since the generated
descriptors are heterogeneous and, due to virtual functions, can not be
trivially copied, the corresponding placement invocations on the
data builder API must not be mixed, but rather given in ordered strikes
and preceded by a dimensioning call to pre-reserve a bulk of storage

However, doing so directly would jeopardise the open and flexible nature
of the node builder API, thereby creating a dangerous coupling between
the implementation levels of the node graph and of prospective library
wrapper plug-ins in charge of controlling details of the graph layout.

The solution devised here entails a functional helper data structure
created temporarily within the builder API stack frames; the detailed
and local type information provided from within the library plug-in
can thereby be embedded into opaque builder functors, allowing to
delay the actual data generation up until the final builder step,
at which point the complete number and size requirements of
connectivity data is known and can be used for dimensioning.
2024-10-20 21:52:00 +02:00
4a963c9fee Invocation: draft how the 1:1-fallback wiring could work
...and as expected, this turns up quite some inconsistencies,
especially regarding usage of the »buffer types«.

Basically, the `PortBuilder` is responsible for the high-level functionality
and thus must ensure the nested `WiringBuilder` is addressed and parameterised
properly to connect all »slots« of the processing function.
 - can use a helper function in the WiringBuilder to fill in connections
 - but the actual buffer types passed over these connectinos are totally
   unchecked at that level, and can not see yet how this danger can be
   mitigated one level above, where the PortBuilder is used.
 - it is still unclear what a »buffer type« actually means; it could
   be the pointer type, but it could also imply a class or struct type
   to be emplaced into the buffer, which is a special extension to the
   `BufferProvider` protocol, yet seems to be used here rather to transport
   specific data types required by the actual media handling library (e.g. FFmpeg)
2024-10-14 04:07:47 +02:00
4df4ff2792 Invocation: consider minimal test setup and verification
__Analysis__: what kind of verifications are sensible to employ
to cover building, wiring and invocation of render nodes?
Notably, a test should cover requirements and observable functionality,
while ''avoiding direct hard coupling to implementation internals...''

__Draft__: the most simple node builder invocation conceivable...
2024-10-13 03:49:01 +02:00
bb9d0107cd Invocation: setup preliminary engine-context
* decision how to provide a default service for tests
   while also allow for configuration of more specific services
 * as starting point for the prototype: use the `TrackingHeapBlockProvider`
   (simply because this is the only implementation available and tested)
2024-10-12 04:17:39 +02:00
a02873a015 Invocation: pass the actual processing function
...need to pass a binding for the actual processing function
in a way that it acts as a ''prototype'' — since the `Feed`,
i.e. the ''Invocation Adapter'' must be generated for each
invocation anew within the current stack frame
(so to avoid spurious heap allocations)
2024-10-11 04:39:40 +02:00
9490192ef8 Invocation: integrate WeavingBuilder into PortBuilder
...seems that the former is well suited to serve as detail builder
used internally by the latter to provide a simplified standard adaptation
for a given processing function.

The integration can be achieved to layer a specialised detail builder class
on top, which can be entered only by specifying the concrete function or lambda
to wrap for the processing; the further builder-API-functions to control
the wiring in detail become thus only accessible after the function type
is known; this allows to place the detail builder as member into the
enclosing port builder and thus to allocate everything within the current
stack frame invoking the builder chain.
2024-10-11 02:45:51 +02:00
409f2f20b8 Invocation: introduce engine-context for dependency injection
...by relying on DI for some effectively global services, notably
the cache provider, the API for building and wiring render nodes
can be simplified to cover only the actual node connectivity
2024-08-03 03:21:59 +02:00
38dd3a738e Invocation: introduce optional output buffer
Doing so directly seems to be a better solution than to inject an OutputBufferProvider;
the latter will still be needed, yet will not be part of the regular weaving pattern,
but used directly at top-level to obtain the output `BuffHandle`, which is then
passed to the `Port::weave()` call
2024-07-31 19:20:44 +02:00
4bda550f68 Invocation: investigate ways to configure the output-info
...still not convinced that this is a good design,
since it seems to subvert the general design to treat one special case.
However, I can't see a good way to address this special case directly
2024-07-30 23:44:55 +02:00
ea183086ca Invocation: Prototyping to clarify buffer type marking
Requirement analysis shows that the ''actual buffer provider'' to use
constitutes yet another independent degree of freedom, which conceivably
must be handled by the Builder internals rather than by the Domain Ontology.

Thus the simple solution to use a `BuffDescr` to mark the type must be augmented
to also allow configuration of the underlying `BufferProvider`, which generates
the descriptor and can later be invoked with this descriptor to ''lock  an actual Buffer.''

In some cases, setup of the buffer types could even be more complicated and require
access to the actual (runtime) invocaton context; such extreme cases however
could be rendered as an extension of the scheme established here,
by storing the (up to now transient) constructor functors persistently.
Which leads to the decision not to care for those extremely complicated
corner cases right now, and thus to construct all buffer descriptors
in the `build()` call
2024-07-24 20:29:37 +02:00
42f8f8d5af Invocation: Prototyping how to setup invocation wiring
...still fighting to find a suitable API to define
how inputs and outputs are connected and mapped to function parameters.

The solution drafted here uses the reshaped `DataBuilder` (≙`lib::SeveralBuilder`)
to add up connections for each »slot«, disregarding the possibility of permutations.
Similar to `NodeBuilder`, a policy template is used to pass down the setup
for an actual custom allocator.
2024-07-24 03:52:44 +02:00