InitRender from Execute()

On 08/08/2018 at 11:07, xxxxxxxx wrote:

User Information:
Cinema 4D Version:   R19 
Platform:   Windows  ; Mac  ;  Mac OSX  ; 
Language(s) :


I have a scene that has a SHADERLINK parameter, initialized with a texture. It works, I can sample, no problem.
But every time I load that scene, I'm getting a INITRENDERRESULT_USERBREAK error when I call InitRender(), from my TagData::Execute().
If I immediately change some parameter to trigger Execute() again, InitRender will succeed and sample as expected.

From the docs I see the error has something to do with threading (Thread has been canceled).
Should I init irs.vd? How? I can't find a way to get a Render* anywhere in the docs to access GetInitialVolumeData()

Here's what I do, in my Execute() :

GeData data;
node->GetParameter( parameterId, data, DESCFLAGS_GET_0 );
auto shader = static_cast<BaseShader*>( data.GetBaseLink() ); 
InitRenderStruct irs( doc );
irs.thread = bt;
auto error = shader->InitRender( irs );

On 09/08/2018 at 06:33, xxxxxxxx wrote:


we probably need more details here. You seem to have a TagData plugin, which links to a shader. Who owns this shader or where is the shader inserted into?
It seems at least unusual to me to call InitRender() from within the execution pipeline. Why do you need to render the shader manually at all?
Please forgive my questions, I might be missing something. Therefore a more detailed explanation of what you are actually trying to do and what's the rough architecture of your plugin could help a lot.

On 10/08/2018 at 17:39, xxxxxxxx wrote:

My shaders are declared in the resource file of a tag, do I still need to insert them in the object to use? If I list the object's shader, there's nothing there.
But so far I just do GetParameter, InitRender and Sample.

It seems at least unusual to me to call InitRender() from within the execution pipeline. Why do you need to render the shader manually at all?

I don't understand the question. The docs make clear that we need to InitRender before Sample. I read and process all the attributes in Execute, is that odd?

Re-reading the BaseShader manual brings me some more questions...

We need to insert the shader in an object to use it, so after we're done do we need to remove it? Using what, GeListNode::Remove() ?

If the shader parameters are updated in the Attribute Manager, should we InitRender again?

That cycle is not clear to me, seems that every time that I need to sample the sader, do I need to do all that? GetParameter, InsertShader, InitRender, Sample, FreeRender, Remove.

On 13/08/2018 at 08:04, xxxxxxxx wrote:


first of all I have to apologize, my question was stupid. I checked our code base and it's fine to sample a shader inside of the execution pipeline. Sorry.

Regarding insertion of the shader. It depends on how the shader gets created, that's linked in your SHADERLINK parameter. If you create the shader manually and add the link, then you need to insert it properly, in this case into the tag. You also don't need to insert and remove it all the time, but you'd insert it once and remove upon destruction. If on the other hand the shader gets created by the user with the shader popup next to the link field, then the shader is already properly inserted and you don't need to care.

On 14/08/2018 at 14:56, xxxxxxxx wrote:

Ok, that clarifies the ownership. I checked everything and looks ok.

But my original problem persists, every time I load a scene, the first time I call InitRender(), it returns INITRENDERRESULT_USERBREAK. All subsequent calls return OK.
That specific shader contains just one simple texture, that exists and is accessible.
What can cause INITRENDERRESULT_USERBREAK? Docs says "Thread has been canceled". I'm initializing InitRenderStruct with the Execute's doc and bt.

I'm using shaders as distribution maps, to generate geometry and other properties based on the object UV, sampled by shader, so it's not used in any material, just to sample.

On 16/08/2018 at 08:31, xxxxxxxx wrote:

Unfortunately I can not reproduce your issue in Cinema 4D SP1 (19.053) on Windows.
I'm using almost exactly your code, except for the cast of GetBaseLink(). I don't understand how this line can work for you. From the BaseLink you need to get the BaseList2D pointer via GetLink() first. Of course you could also do a GetLink() on the GeData directly.

So, we will need to dig further, what's causing the issue on your end. My tag is registered with the flags TAG_EXPRESSION and TAG_VISIBLE. Otherwise I implemented Execute(), only.
Which version of Cinema do you use? Can you maybe strip down your code to the bare minimum needed to reproduce the issue?

From your first post I forgot to answer the question about VolumeData. You don't need to initialize it, just set it to nullptr.

On 16/08/2018 at 16:48, xxxxxxxx wrote:

Hi Andreas,

Thanks for your help. I was stripping down the project, and indeed I don't use GetBaseLink() that way, there's some missing code in my snippet.

But then I thought of something...
The texture is  a PNG, RGB, 8bit, 4096 by 4096. I had tried different texture formats before and the shader always failed to initialize, but now I tried slowly reducing the resolution and when it's 2048 by 2048, I stop seeing initialization errors.

Maybe the shader is taking too long to initialize and breaks something, is that a known bug?
Should we limit the artists to using max 2k textures?


On 17/08/2018 at 08:59, xxxxxxxx wrote:

Hi Roger,

that was the information I was missing. With an image larger than 4k I can reproduce the issue, although not reliably. It doesn't happen all the time on scene load and then again sometimes it also happens when creating the shader.
I need to discuss this with development next week. So please stay tuned.