10 minute rewrite and it’s all working perfectly. Thanks for your info guys... huge informational leap.
-Nathan From: Nathan Rusch Sent: Monday, October 31, 2011 4:10 PM To: Nuke plug-in development discussion Subject: Re: [Nuke-dev] Altering only a specific ChannelSet in engine Thanks for the quick replies guys. So currently the issue is that, even if I’m only getting a request for mask.a, if the op hash has been updated, I’m always get()-ing Mask_RGB in my single-threaded block no matter what. I’ll do some rewriting. Much appreciated. -Nathan From: Jonathan Egstad Sent: Monday, October 31, 2011 3:54 PM To: Nuke plug-in development discussion Subject: Re: [Nuke-dev] Altering only a specific ChannelSet in engine You must not make ANY assumptions about what channels are being requested of you. Your code crashes because you blindly request row[z] from opChannels which is Mask_RGB, but what happens if a downstream node asks for Alpha (or Z-Depth, or anything other than RGB)? You will blindly do a row[Chan_Alpha], and that will return NULL because that channel isn’t in your input row because you never requested it, and will immediately crash Nuke. You should ‘erase’ the output of all requested channels for which you do not wish to provide data. Usually it's easiest to call get() on the input and pass the channel mask the engine is getting so at least the add'l channels get filled in, then you simply modify the ones you want. Or better yet you remove the channels you're going to modify from the get() channel mask so the channels aren't processed twice for no reason (unless you need the channel data as source.) input(0)->get(y, x, r, channels, row); // fill my writable channels or ChannelSet c1(channels); c1 -= my_writable_channels; input(0)->get(y, x, r, c1, row); // fill my writable channels -jonathan From: nuke-dev-boun...@support.thefoundry.co.uk [mailto:nuke-dev-boun...@support.thefoundry.co.uk] On Behalf Of Nathan Rusch Sent: Monday, October 31, 2011 3:17 PM To: Nuke-Dev Subject: [Nuke-dev] Altering only a specific ChannelSet in engine Hey all, So I’m apparently still confused about what (not) to call in Iop::_validate, Iop::_request, and Iop::engine when I only need to do things to certain channels. I’ve written a (theoretically) dead-simple Iop that averages the incoming RGB channels in place, and passes any other channels through. However, there’s either something wrong with my code, or I’m running into a Nuke bug I encountered a couple weeks ago with channel requests, because I keep getting viewer lock-ups and messages like 'Warning: [node name]: get(channels=0x7), but request(channels=0x2000)' in the terminal. I’d like to rule out the "bad user code" side of things and get any issues cleaned up on my side, so I’d appreciate it if someone could take a look and tell me if I’m doing something ass-backwards here. The rough summary of what the op should be doing is: 1) Only changing rgba.red, .green, and .blue. 2) In engine, aggregating each of those channels into a private double[3] array, dividing the aggregated values by the pixel count, and storing those averages in another private float[3] array. 3) Unlocking the engine threads and, for any channels not intersecting Mask_RGB, copying the input channel straight through; otherwise, writing the appropriate component of the average array to the entire output buffer. Like I said, I seem to still be overlooking something regarding what channels to set_out, request, and get(), so there may be some pretty stupid mistakes in here (on that note, it would be great if there were some better examples of how to use each of those steps somewhere). I’ve tried tweaking various ChannelSets and calls in different methods, and there are still a few code optimizations I think I could do, but right now I’m having no luck. CODE TIME: ---------------------------- void _validate(bool for_real) { _firstTime = true; copy_info(); set_out_channels(Mask_RGB); Iop::_validate(for_real); } void _request(int x, int y, int r, int t, ChannelMask channels, int count) { input0().request(x, y, r, t, channels, count); } void engine(int y, int x, int r, ChannelMask channels, Row& out) { ChannelSet opChannels = Mask_RGB; { Guard g(_engineLock); if (_firstTime) { // Reinitialize value containers for (int i = 0; i < 3; i++) { _avgPix[i] = _pixAggregate[i] = 0.0f; } Format format = input0().format(); const int fx = format.x(); const int fy = format.y(); const int fr = format.r(); const int ft = format.t(); const int height = ft - fy; const int width = fr - fx; const unsigned long int pixCount = width * height; // Allocate cache interest // If I uncomment these lines, I will get errors about // interest(channels=) instead of get(channels=) // Interest interest(input0(), fx, fy, fr, ft, opChannels, true); // interest.unlock(); for (int ry = fy; ry < ft; ry++) { // Set any progress bars progressFraction(ry, ft - fy); // Get the corresponding Mask_RGB row from the input Row row(fx, fr); row.get(input0(), ry, fx, fr, opChannels); if (aborted()) return; // Aggregate pixel values from Mask_RGB into container array int chan = 0; foreach(z, opChannels) { const float *CUR = row[z] + fx; const float *END = row[z] + fr; while (CUR < END) { _pixAggregate[chan] += (float)*CUR; CUR++; } chan++; } } // Calculate the average for each channel for (int c = 0; c < opChannels.size(); c++) { _avgPix[c] = _pixAggregate[c] / pixCount; } _firstTime = false; } } // Lock out of scope // Get the full row from the input Row in(x, r); in.get(input0(), y, x, r, channels); if (aborted()) return; // Fill all pixels in Mask_RGB from _avgPix int outChan = 0; foreach(z, channels) { if (!intersect(z, opChannels)) { // A channel we don't want to modify (may want to // change this to a straight memcpy eventually). out.copy(in, z, x, r); } else { float *CUR = out.writable(z) + x; const float *END = out[z] + r; while (CUR < END) { *CUR++ = _avgPix[outChan]; } outChan++; } } } -Nathan (CONFIDENTIALITY NOTICE: The information contained in this email may be confidential and/or privileged. This email is intended to be reviewed by only the individual or organization named above. If you are not the intended recipient, or an authorized representative of the intended recipient, you are hereby notified that any review, dissemination or copying of this email, or the information contained herein is strictly prohibited. If you have received this communication in error, please notify the sender by return email and delete this email from your system. Thank You.) _______________________________________________Nuke-dev mailing listnuke-...@support.thefoundry.co.uk, http://forums.thefoundry.co.uk/http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-dev -------------------------------------------------------------------------------- _______________________________________________ Nuke-dev mailing list Nuke-dev@support.thefoundry.co.uk, http://forums.thefoundry.co.uk/ http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-dev -------------------------------------------------------------------------------- _______________________________________________ Nuke-dev mailing list Nuke-dev@support.thefoundry.co.uk, http://forums.thefoundry.co.uk/ http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-dev
_______________________________________________ Nuke-dev mailing list Nuke-dev@support.thefoundry.co.uk, http://forums.thefoundry.co.uk/ http://support.thefoundry.co.uk/cgi-bin/mailman/listinfo/nuke-dev