took a while to strip this one down to a demo patch:
a plugin with an output with AllowFeedback enabled breaks some subsequent pins in the first frame.
in the demo patch the error surfaces as pin prepare error in core vvvv, in the real patch it surfaces in the next IDiffSpread down the chain.
although the demo error only exists in the first frame, in real it completely breaks the subsequent plugins (the pins on the ones i could inspect in debug just stay null)
I was guessing allowing the ui to connect in a loop fashion requires to also make sure that evaluation is stopped at some point.
That’s why i tried to use “AutoEvaluate = false” on the FrameDelayed node.
However the bug is still there. So this is tracked now.
Please try some workaround for now. I attached one where the “Feeback” Output is of type double. FeedbackPinBug.zip (27.0 KB)
just curious: FrameDelay (Transform) isn’t really helping here?
transform is actually just the output type of the demo. the real case is an instance of a custom class, so i just wanted to show it on linktype node and not value type. unfortunately serializing and deserializing to is not an option.
a workaround now is to have a switch + onopen after the framedelay node. but there’s nothing i can do to avoid the bug from within the plugin. thats why the demo doesn’t even write anything to the pin, also not flushing doesn’t help.
since double is bugfree, is it something with nodetype?
currently in your example it’s still not obvious where to start evaluating and where to stop. i think you shouldn’t Sync your input. Otherwise you risk a circular dependency/call stack. (so in order to give you the data of your input vvvv tries to evaluate your outputs before written to or similar nonsensical behavior).
We should first understand what you’re trying to achieve conceptually before implementing it.
alright, debugged. seems like i encountered quite a cornercase.
the scenario is a FrameDelay and something like S+H for a custom datatype. Both obviously need to evaluate every frame in order to ensure a correct result when asked for it:
Framedelay has to evaluate, to be able to have the data of the previous frame, even if the graph was not active the last frame.
S+H has to evaluate, since the user might trigger ‘save’ while the no other node is pulling from downstream at that point.
the bug doesn’t surface now, when using the same technique as elias did in the generic framedelay implementation: not decorating with autoevaluate but call evaluate on the plugin through OnPrepareGraph every frame.
(the generic implementation didn’t work for me, guess since my type is highly mutable and needs a deep copy stored instead of just copying to in to output at after node evaluation)
still curious, what bug exactly that was.
and also, what does a red pin in debug mode mean? in your last example ‘nofeedbackpinbug’ if you set autoevaluate to true on the PassThrough node and restart, the input on the iobox below will be red.
Debugging revealed that the bug you encountered was related to the transform pins. They are implemented in a quite special way as they are designed to not only be able to propagate matrices but also “arbitrary” transforms. This is due to a very old design decision. And because of this, the way they are handed over to the plugin interface, is also special.
But you noted that transform was just an example. You have another class that you want to framedelay. If you are still stuck then please give me some other example that breaks to be able to concentrate on the actual issue.
The recommended way is to base your work on this:
did you try to write your own Copier implementation? Try to inherit from this:
Hopefully your main setup of the framedelay node now is comparably compact as these ones:
here are examples of special Copier implementations:
should the AllowFeedback attribute be deprecated then?
basing of the generic framedelay unfortunately is not an option. was the first thing i tried.
that implementation doesn’t keep a deepcloned buffer around and ‘just’ assumes that the output is read before the new input is copied onto it. while this works fine for most cases my class is a container carrying serveral references around. strange case. i’ll show you next time i’m around b
the interface IPluginFeedbackLoop allows you to be more specific and make the decision of if the connection would lead to a cycle depend on a pair pins.
So it feels like the better approach.
The other approach is still supported, but i guess you are right. I’ll mark the attribute as deprecated.
i’ll discuss inner workings with the team and come back to you. I would have thought that this generic implementation should be a good base for you, but you are right: it looks like some assumption is in there. I’ll come back to you.
we hope that with the changes done in this commit you should be able to actually use the generic implementation as the base of your implementation. Please (deep) clone your mutable objects with your Copier< YourMutableType>.