Your browser does not seem to support JavaScript. As a result, your viewing experience will be diminished, and you have been placed in read-only mode.
Please download a browser that supports JavaScript, or enable it if it's disabled (i.e. NoScript).
On 10/10/2017 at 04:55, xxxxxxxx wrote:
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
On 11/10/2017 at 01:26, xxxxxxxx wrote:
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.
On 18/10/2017 at 06:06, xxxxxxxx wrote:
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,