Plugin Cafe Homepage
Forum Home Forum Home > Plugin Cafe > SDK Help
  New Posts New Posts
  FAQ FAQ  Forum Search   Register Register  Login Login

Crash in cloned gradient Shader

 Post Reply Post Reply
Author
Message
NiklasR View Drop Down
Member
Member


Joined: 2010 Dec 13
Location: Germany
Online Status: Offline
Posts: 2558
Post Options Post Options   Quote NiklasR Quote  Post ReplyReply Direct Link To This Post Topic: Crash in cloned gradient Shader
    Posted: 2017 Oct 10 at 4:55am

User Information:

Cinema 4D Version:    
Platform:      Mac OSX  ; 
Language(s):     C++  ;   

---------

Hi!

One of our shaders is used as a "reference shader" where you can link a shader from anywhere else
in the document (in this case, the shader sits on a BaseObject) and reproduce it. On InitRender(), this
referenced shader is cloned and inserted into a temporary branch to ensure that the shader is available
to the document.

In case it matters, this "reference shader" sits on the very same object, too.


Unfortunately, a crash appears quite frequently when we copy the BaseObject that hosts both shaders.
This crash is only reproducible when the source shader is a Gradient Shader. It appears to happen only
when the object is copied multiple times at once or in a short period of time. Also, I wasn't able to
reproduce this issue on Windows.

Is there anything special about the Gradient shader that could prevent it from being sampled this way?

INITRENDERRESULT ReferenceShader::InitRender(
BaseShader* shader, const InitRenderStruct& irs)
{
BaseContainer* bc = (shader ? shader->GetDataInstance() : nullptr);
if (!shader || !bc) return INITRENDERRESULT_UNKNOWNERROR;
if (!m_head) return INITRENDERRESULT_OUTOFMEMORY;

// We pass nullptr for the document because we do actually want to allow
// retrieving a shader from another document (for the shader preview).
m_subShader = (BaseShader*) bc->GetLink(FIXTURESHADER_SUBSHADER, nullptr, Xbase);
if (m_subShader) {
// Check if the shader is in the hierarchy.
Bool needsClone = true;
for (BaseShader* curr = shader->GetDown(); curr; curr = curr->GetNext()) {
if (curr == m_subShader) {
needsClone = false;
break;
}
}

m_subShaderCloned = needsClone;
if (needsClone) {
m_subShader = (BaseShader*) m_subShader->GetClone(COPYFLAGS_0, nullptr);
if (!m_subShader) return INITRENDERRESULT_OUTOFMEMORY;
m_head->InsertLast(m_subShader); // Needs to be removed and deallocated in FreeRender()
}

auto res = m_subShader->InitRender(irs);
if (res != INITRENDERRESULT_OK) {
if (m_subShaderCloned) BaseShader::Free(m_subShader);
m_subShader = nullptr;
return res;
}
}

// ...
return INITRENDERRESULT_OK;
}


void ReferenceShader::FreeRender(BaseShader* shader)
{
if (m_subShader) {
m_subShader->FreeRender();
if (m_subShaderCloned) {
m_subShader->Remove();
BaseShader::Free(m_subShader);
}
m_subShader = nullptr;
}

// ...
}


Vector ReferenceShader::Output(BaseShader* shader, ChannelData* cd) {
// ...

Float u, v = ...;

if (m_subShader) {
ChannelData data = *cd;
data.p = Vector(u, v, 0);
return m_subShader->Sample(&data) * m_sampling.brightness; // << CRASH when m_subShader is a Gradient Shader
}

// ...
return Vector();
}
Int32 ReferenceShader::GetBranchInfo(
GeListNode* node, BranchInfo* branches,
Int32 max, GETBRANCHINFO flags)
{
Int32 count = 0;
if (count < max) {
branches[count].head = m_head;
branches[count].name = nullptr;
branches[count].id = Xbase;
branches[count].flags = BRANCHINFOFLAGS_HIDEINTIMELINE;
count++;
}
return count;
}

Tips or hints are also appreciated, of course. :)

Thanks,
-Niklas


Edited by NiklasR - 2017 Oct 10 at 5:50am
Back to Top
Andreas Block View Drop Down
Forum Moderator
Forum Moderator
Avatar

Joined: 2014 Oct 01
Location: Hannover
Online Status: Offline
Posts: 1599
Post Options Post Options   Quote Andreas Block Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Oct 11 at 1:26am
Hi Niklas,

we are not aware of any peculiarities of the gradient shader.
Can you provide us with a crash report (e.g. via email)? Another option could be to provide us with your plugin, so we could dig into the crash.

Cheers,
Andreas
SDK Support Engineer
Back to Top
NiklasR View Drop Down
Member
Member


Joined: 2010 Dec 13
Location: Germany
Online Status: Offline
Posts: 2558
Post Options Post Options   Quote NiklasR Quote  Post ReplyReply Direct Link To This Post Posted: 2017 Oct 18 at 6:06am
Thanks to the SDK support team, they figured out that ChannelData::texflag was set so that
GET_TEX_CHANNEL() would return CHANNEL_BUMP, which in turn requires ChannelData::vd
to be not-nullptr. The issue on my side was a bit further up the call stack, where I created a
new ChannelData on the stack without initializing the texflag member (the ChannelData
constructor only sets vd = nullptr, leaving texflag at a random value).

/* Returns an empty ChannelData object. The default constructor only explicitly initializes
* the #ChannelData::vd member, leaving #ChannelData::texflag and others at a random value.
* This random value for texflag can be especially problematic when it results in
* #GET_TEX_CHANNEL() to return #CHANNEL_BUMP, which requires #ChannelData::vd to be set,
* leading to crashes in for example the C4D gradient shader.
*/
inline ChannelData GetEmptyChannelData() {
ChannelData r;
r.t = 0.0;
r.texflag = 0;
r.off = 0.0;
r.scale = 0.0;
return r;
}


Cheers,

Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down

Bulletin Board Software by Web Wiz Forums® version 9.61 [Free Express Edition]
Copyright ©2001-2009 Web Wiz

This page was generated in 0.109 seconds.