Copy link to clipboard
Copied
Hi,
Sorry for adding a new question in the forum but I didin't find the answer. I'm working on an iteration like in CCU exemple and I'd like to access to the value of pixels around. For now I use *sampleIntegral32, but it's not optimised during an iteration. I see the iteration works with pointers for input_pixel and outputpixel but I don't find the good solution to access by this way...
Has someone an Idea ?
thanks again.
perhaps the "in pixel" pointer is indeed a direct ref to the input buffer,
in which case you can do some pointer math to move to adjacent pixels.
PF_Pixel *next = inP + 1;//that will give you the next pixel on the same
line.
but before going into these shenanigans, are you acquiring and releasing
the sample suite on every pixel, or are you getting a reference to that
suite before calling the iteration function and use the reference inside
the iteration function?
because getting and releasing the suite o
...Copy link to clipboard
Copied
perhaps the "in pixel" pointer is indeed a direct ref to the input buffer,
in which case you can do some pointer math to move to adjacent pixels.
PF_Pixel *next = inP + 1;//that will give you the next pixel on the same
line.
but before going into these shenanigans, are you acquiring and releasing
the sample suite on every pixel, or are you getting a reference to that
suite before calling the iteration function and use the reference inside
the iteration function?
because getting and releasing the suite on every pixel will really weigh
down on your performance...
in my opinion, when you need a lot of integer samples of other pixels, it's
best to access the buffers directly and use iterate_generic instead. you
can do a ton more optimizations than you can with the regular iteration
suites.
Copy link to clipboard
Copied
thank you. Yes I do it on every Pixel but I 'can't use iterate_generic in this situation because I store and send the value to a math parser during the iteration for each pixels.
During the test, If I do a 3*3 matrix, it's not too low but higher matrices array is the best way to get error. So I will stay with this low number for now
thanks a lot
Copy link to clipboard
Copied
i see no reason why not to use iterate_generic. when you'll want to do the
next optimization step you should go down this route.
you can have each thread handle a single buffer line. you can save a TON of
overhead when optimizing for a line as opposed to a pixel.
Copy link to clipboard
Copied
I'll do some test and tell you the result
. Does Iterate_generic work only for 8 bits ?
Copy link to clipboard
Copied
iterate_generic doesn't care what you do with it. it only calls a function
n times using all available threads.
in that function, you can do whatever you want. ideally, you'll call
iterate_generic with the number of lines in your buffer, and in the
iteration function you'll set your pixel pointers for the beginning of the
line, and advance them in a loop.
this way you won't need to calculate the relative location in ram of the
adjacent pixels. you could do it once at the beginning of the line, and
then advance all pointers by 1.
Copy link to clipboard
Copied
You're right iterate generic get some result faster in other projects.
But in the current situation I've a problem.
There is a classical iteration (like CCU) and inside the iteration there is an other iteration for each pixels (3*3 around.
I tried to call the iterate generic on the 3*3part and the result is slower...
Copy link to clipboard
Copied
oh, god no! calling iterate generic on each pixel is hell! you'd have a ton of overhead!
here's an example code for the call for each line. i'm writing pseudo code directly here, so it's not tested...
call such a function with iterate_generic with the number of lines in the buffer. (assuming input and output buffers are of the same size)
for a predictably advancing group of pixel pointers, this will be by far faster than checking out pixels with the sample suite for each coordinate.
PF_Err LineIterationFunction(iterIndex, numIter, refcon) {
PF_EffectWorld inW = ((refconStruct*)refcon)->inW;//cast input buffer here.
PF_EffectWorld outW = ((refconStruct*)refcon)->outW;//cast output buffer here.
int w = inW->width;
int h = inW->height;
int x = 0;
int y = iterIndex;
PF_Pixel *outP = outW->data + (outW->rowbytes / sizeof(PF_Pixel)) * y;//get pointer to first pixel of line y in output buffer.
PF_Pixel *inP = inW->data + (inW->rowbytes / sizeof(PF_Pixel)) * y;//get pointer to first pixel of line y in input buffer.
PF_Pixel *in00 = inP - (inW->rowbytes / sizeof(PF_Pixel)) - 1;//top left pixel in 3X3.
PF_Pixel *in10 = in00 + 1;//top middle pixel in 3X3.
PF_Pixel *in20 = in10 + 1;//top right pixel in 3X3.
PF_Pixel *in01 = inP - 1;//mid left pixel in 3X3.
PF_Pixel *in21 = inP + 1;//top right pixel in 3X3.
PF_Pixel *in02 = inP + (inW->rowbytes / sizeof(PF_Pixel)) - 1;//bottom left pixel in 3X3.
PF_Pixel *in12 = in02 + 1;//bottom middle pixel in 3X3.
PF_Pixel *in22 = in12 + 1;//bottom right pixel in 3X3.
for(x; x < w; x++) {
//checking the validity of the pointers. (inP is always valid)
if(!y) {} //the top line is not valid. don't read in00, in10, and in20.
if(y >= h - 1) {} //the bottom line is not valid. don't read in02, in12 and in22.
if(!x) {}//left line is not valid. don't read in00, in01 and in02.
if(x >= w - 1) {} //right line is not valid. don't read in20, in21 and in22.
//do stuff with the valid pointers, and write to outP.
//advance all pixel pointers by 1 to the right.
outP++;
inP++;
in00++;
in10++;
in20++;
in01++;
in21++;
in02++;
in12++;
in22++;
}
}
Copy link to clipboard
Copied
ha I didn't use pointers for each pixel around but now it's looking clear.
I still have a problem creating a function for iteration but it comes from an external dependencie.
thanks again
Copy link to clipboard
Copied
the iterate_generic processing function is not technically different than the pixel iteration callback function in any meaningful way.
but hey, you know your needs better than i do.
Copy link to clipboard
Copied
In the CCU exemple every iterations happens in the same threads that's why the iteration with the dependencies works.
the structure looks like :
PF_err Render
-checkout params
-Use a parser (from exptrk) to compile and return an expression Expr (ask a lot of ressources so I've to call it only once)
-loop for(y < height)
loop for(x <width)
Expr returns value for each pixel
If I set the expression in a pointer to send the iterate_generic (or classical iteration function) I get noisy result. I don't know why but it's impossible to split them. I'm looking around because as you said generic iteration is faster
Copy link to clipboard
Copied
Well, is the function evaluation your expression for each pixel actually threadsafe?
Copy link to clipboard
Copied
wait, did you use the pixel iteration callback to begin with? i'm starting
to think i assumed falsely here.
in any case, toby's question is the right one to ask at this point...
On Tue, Oct 2, 2018 at 3:54 PM Toby (reduxFX) <forums_noreply@adobe.com>
Copy link to clipboard
Copied
If you don't trust or don't want to use the iteration functions provided by Adobe, you can also simply roll your own using std::thread or boost::thread or whatever native thread library your operating system provides. This can also help you in testing thread-safety, and you can run it not only from a plugin within AE, but also as a standalone app, which might be easier to debug/test.
Copy link to clipboard
Copied
In some exemples the lib uses std::thread. I did some test outside of AE and it works fine.But the paser function itslef is not threadsafe.I've just checkout the readme.
sorry I m discovering the dark side of the multithreading, I didn't t work around yet.
UPDATE : forget it. I found the solution with the external lib and know, It's possible to use the Iterate generic function. ![]()
The first test seems to look so faster...
Tanks Shachar and Toby
Find more inspiration, events, and resources on the new Adobe Community
Explore Now