In a Point Wrangle, is there a way to mark a variable as only needing to be calculated once per cook, rather than once per point?

   2341   4   2
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
I've written a simple bit of Vex in a Point Wrangle that enlarges any points that'll end up less than a pixel wide in the render. It reduces the point's Alpha to compensate.

The calculation is based on a factor derived from the camera resolution, sensor size, and focal length - this only needs calculating once per frame, so doing it in the point wrangle itself means it'll be evaluated for every single point.

I've got round this by creating another wrangle above that calculates the factor and stores it in a detail attribute: but is there a way of doing it all in the one wrangle, rather than two? A way of saying “you'll need to run this bit of code once, then you can run over all the points”?

Some #pragma voodoo?

Or is the VEX compiler smart enough to recognise variables that won't change per-point, and just calc/cache them once?
User Avatar
Member
8045 posts
Joined: 9月 2011
Offline
You can channel reference a parameter that computes the value using an expression (hscript expression/python). Or like you said you can use a pre-compiler define, but this is not recommended if the value changes over time as the code would need to be recompiled/optimized every time step.
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Ooo - hasn’t thought of using a parameter to store it: that’s super. Much tidier, means I can store the whole shebang in a wrangle preset rather than an HDA. Thanks!
Edited by howiem - 2018年10月23日 13:18:38
User Avatar
スタッフ
6413 posts
Joined: 7月 2005
Offline
howiem
Or is the VEX compiler smart enough to recognise variables that won't change per-point, and just calc/cache them once?

Pretty much this.

There are three levels of computation:
1) Compile time
2) Once per point block (uniform)
3) For every point

If you have code like:

s@foo = sprintf("hello%d", 3);

The sprintf() will actually be computed at compile time.

If you have code like:

s@foo = sprintf("hello%d", ch("localparm"));

the ch() function has no per-point dependency, so will be marked uniform. Thus the sprintf() likewise will be uniform and only evaluated once per point-block. Point blocks are 1024 in size, so for almost all cases are pretty much equivalent to only evaluating it once outside the loop. It has to be pretty exceptional for me to consider pre-computing something rather than trusting the VEX compiler.
User Avatar
Member
146 posts
Joined: 9月 2011
Offline
Thanks /u/jlait: that's great to know. Love these insights into the back-end.

Thinking about it, the VEX stuff in a lot of the factory SOPs - like if you dive into a Bend SOP and nose around - seems to contain plenty of calculations that will remain static across all the elements being processed, so I should have just trusted the compiler to be smarter than me
  • Quick Links