Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem rendering multiple scripted objects (Groovy related) #312

Open
peteihis opened this issue Jan 25, 2024 · 5 comments
Open

Problem rendering multiple scripted objects (Groovy related) #312

peteihis opened this issue Jan 25, 2024 · 5 comments

Comments

@peteihis
Copy link
Contributor

peteihis commented Jan 25, 2024

Strange things happen, when you try to render a scene with multiple ScriptedObjects. Attached a file to demonstrate. The two cubes respond fine to the time slider on the scene but rendering keeps randomly losing one of them. Sometimes they may even swap places.

Scripted cubes.zip

I have ran into this before, but I can't remember the exact case. At that time the objects were more complex and it involved occasionally leaving the construction of some of the objects incomplete. As I recall, I traced the problem to multiple threads feeding data to some more static part of the rendering (possibly at building the triangulated scene for RayTracer), so that one object was not finished before the next one was pushed into the process.

@peteihis
Copy link
Contributor Author

peteihis commented May 24, 2024

Did a little research...

It would seem that Raytracer.addObject() is not thread safe, when it has to recursively call itself. That happens, when theObject is and ObjectCollection, it this case a ScriptedObject.

Adding some debugging code shows that addObject() always finds both of the first level objects (scripts), but sometimes misses one of the cubes the scripts produce. Setting addObject synchronized naturally takes care of the problem but then we'd lose (some of the) benefit of parallel processing.

As I recall, in the earlier case the scripted object was supposed to create arrow heads out of primitives by boolean operations and in that case the outcome was in most cases only partially made as if the object from the collection had been read before the script had completed the build. That would also explain what happens here.

If that theory is correct, the question would be, how can it be made sure that running the script has been competed before addObject() requests the content?

Edited a bit.

@peteihis
Copy link
Contributor Author

peteihis commented May 25, 2024

So, the problem is that Groovy is not thread safe! -- This is actually nothing new, it tends to fail with recursion levels and things of that sort too...

I changed the objects so that one of them is a Cylinder and one a Cube. When I render the 1 second movie, sometimes one of the objects is missing entirely and sometimes their position coordinates are confused...

Scripted primitives.zip

I did not quite understand what the mechanism that triggers updating the ScriptedObjects is, but it turns out that SriptedObject.getObjectScript() is visited twice for each rendered frame. Once before Raytracer.addObject() and once after. Apparently the first one happens in the model scene and addObject() triggers the latter one is for the raytracing scene. With Groovy the latter visit is sometimes missing for one of the objects (typically looks like the 1st one on the list). Other times both objects end up in the same coordinates.

In the coordinates swapping case I find it a bit strange that the coordinates that are changing places are not in the script, they are the Scene position coordinates. Internally the example scripts only use new CoordinateSystem().

When I change the language to BeanShell the scripts work as expected.

@peteihis peteihis changed the title Problem rendering multiple scripted objects Problem rendering multiple scripted objects (Groovy related) May 25, 2024
@peteihis
Copy link
Contributor Author

And a bit more poking....

Making all the object declarations even "more local" to addObject() ... instanceof ObjectCollection did nothing. It looks that, when the objects gets to Groovy space they will be mixed up anyway, what ever you do. Defining addObject() synchronized seems to be the only way to tackle this issue.

I wonder if it would be possible to create a "safe mode" that would be switched on is a ScriptedObject is said to be in Groovy? The SafeMode would run Raytracer.addObject() synchronized, otherwise normally? This would obviously require a precheck before calling addObject() in RaytracerRenderer.buildScene().

@makiam
Copy link
Contributor

makiam commented Jul 3, 2024

So, the problem is that Groovy is not thread safe

May we read this as "old 2.1.2 groovy is not thread safe" ?

@peteihis
Copy link
Contributor Author

peteihis commented Jul 3, 2024

May we read this as "old 2.1.2 groovy is not thread safe" ?

I have no idea if these issues would have been fixed in later versions. All I know, is that in AoI both, threads and recursion are poison, when Groovy is involved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants