HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SOP_PrimVOP.C
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2024
3  * Side Effects Software Inc. All rights reserved.
4  *
5  * Redistribution and use of Houdini Development Kit samples in source and
6  * binary forms, with or without modification, are permitted provided that the
7  * following conditions are met:
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  * 2. The name of Side Effects Software may not be used to endorse or
11  * promote products derived from this software without specific prior
12  * written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE `AS IS' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
17  * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
20  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
22  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
23  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  *----------------------------------------------------------------------------
26  * PrimVOP SOP
27  */
28 
29 #include "SOP_PrimVOP.h"
30 
31 #include <SHOP/SHOP_Node.h>
34 #include <GVEX/GVEX_GeoCommand.h>
35 #include <GU/GU_Detail.h>
36 #include <GEO/GEO_Primitive.h>
37 #include <OP/OP_AutoLockInputs.h>
38 #include <OP/OP_Channels.h>
39 #include <OP/OP_Operator.h>
40 #include <OP/OP_Director.h>
41 #include <OP/OP_OperatorTable.h>
42 #include <OP/OP_Caller.h>
43 #include <OP/OP_NodeInfoParms.h>
44 #include <OP/OP_VexFunction.h>
45 #include <PRM/PRM_DialogScript.h>
46 #include <PRM/PRM_Include.h>
47 #include <PRM/PRM_SpareData.h>
48 #include <CVEX/CVEX_Context.h>
49 #include <CVEX/CVEX_Value.h>
50 #include <VEX/VEX_Error.h>
51 #include <UT/UT_Array.h>
52 #include <UT/UT_DSOVersion.h>
53 #include <UT/UT_Interrupt.h>
54 
55 using namespace HDK_Sample;
56 void
58 {
59  table->addOperator(new OP_Operator(
60  "hdk_primvop",
61  "PrimVOP",
65  1,
66  1,
68 }
69 
70 static PRM_Default scriptDefault(PRM_DialogSopVex, "null");
71 
72 
73 static PRM_Name names[] = {
74  PRM_Name("script", "Script"),
75  PRM_Name("clear", "Re-load VEX Functions"),
76  PRM_Name("autobind", "Autobind by Name"),
77  PRM_Name("bindings", "Number of Bindings"),
78  PRM_Name("shoppath", "Shop Path"),
79  PRM_Name("vexsrc", "Vex Source"),
80 };
81 
82 static PRM_Name vexsrcNames[] =
83 {
84  PRM_Name("myself", "Myself"),
85  PRM_Name("shop", "Shop"),
86  PRM_Name("script", "Script"),
87  PRM_Name(0)
88 };
89 static PRM_ChoiceList vexsrcMenu(PRM_CHOICELIST_SINGLE, vexsrcNames);
90 
92 
95 {
97  &names[5], 0, &vexsrcMenu),
100  &names[4], 0, 0, 0, 0,
103  1, &names[0], &scriptDefault),
108  PRM_Template()
109 };
110 
111 
112 OP_Node *
114 {
115  return new SOP_PrimVOP(net, name, entry);
116 }
117 
118 
120  : SOP_Node(net, name, entry),
121  // Set up our code generator for CVEX
122  myCodeGenerator(this,
125  1, 1)
126 {
127  // This indicates that this SOP manually manages its data IDs,
128  // so that Houdini can identify what attributes may have changed,
129  // e.g. to reduce work for the viewport, or other SOPs that
130  // check whether data IDs have changed.
131  // By default, (i.e. if this line weren't here), all data IDs
132  // would be bumped after the SOP cook, to indicate that
133  // everything might have changed.
134  // If some data IDs don't get bumped properly, the viewport
135  // may not update, or SOPs that check data IDs
136  // may not cook correctly, so be *very* careful!
138 }
139 
141 {
142 }
143 
144 
145 OP_ERROR
147 {
148  fpreal t = context.getTime();
149 
150  // We must lock our inputs before we try to access their geometry.
151  // OP_AutoLockInputs will automatically unlock our inputs when we return.
152  // NOTE: Don't call unlockInputs yourself when using this!
153  OP_AutoLockInputs inputs(this);
154  if (inputs.lock(context) >= UT_ERROR_ABORT)
155  return error();
156 
157  duplicateSource(0, context);
158 
159  // Build our VEX script, either from the .vex file, or
160  // from the SHOP, or from the contained VOPs.
161  UT_String script;
162  buildScript(script, context.getTime());
163 
164  // If script is null, default to null script.
165  if (!script.isstring())
166  {
167  script = "null";
169  "No script specified. Using null.");
170  }
171 
172  // Parse the script's parameters.
173  char *argv[4096];
174  int argc = script.parse(argv, 4096);
175 
176  UT_AutoInterrupt boss("Executing Volume VEX");
177 
178  // This op caller is what allows op: style paths inside
179  // the CVEX context to properly set up dependencies to ourselves
180  // Ie, if you refer to a point cloud on another SOP, this
181  // SOP needs to recook when the referred to SOP is coooked.
182  OP_Caller caller(this, context.getContextOptionsStack(),
183  context.getContextOptions());
184 
185  // Actually process the vex function
186  executeVex(argc, argv, t, caller);
187 
188  return error();
189 }
190 
191 void
192 SOP_PrimVOP::executeVex(int argc, char **argv,
193  fpreal t,
194  OP_Caller &opcaller)
195 {
196  CVEX_Context context;
197  CVEX_RunData rundata;
198 
199  // Note that this is a reasonable level to multithread at.
200  // Each thread will build its own VEX Context independently
201  // and thus, provided the read/write code is properly threadsafe
202  // be threadsafe.
203 
204  // Set the eval collection scope
206  getChannels(), opcaller.getContextOptionsStack(),
207  opcaller.getContextOptions());
208 
209  // The vex processing is block based. We first marshall a block
210  // of parameters from our primitive information. We then bind
211  // those parameters to vex. Then we process vex, and read out
212  // the new values.
213  const int chunksize = 1024;
214  UT_Array<int> primid(chunksize, chunksize);
215  UT_Array<exint> procid(chunksize, chunksize);
216 
217  // Set the callback.
218  rundata.setOpCaller(&opcaller);
219 
220  // If multithreading, each thread should allocate its own
221  // geocmd queue.
223 
224  // In order to sort the resulting queue edits, we have to have
225  // a global order for all vex processors.
226  rundata.setProcId(procid.array());
227 
228  // These numbers are to seed the queue so it knows where to put
229  // newly created primitive/point numbers.
230  geocmd.myNumPrim = gdp->getNumPrimitives();
231  geocmd.myNumVertex = gdp->getNumVertices();
232  geocmd.myNumPoint = gdp->getNumPoints();
233 
234  rundata.setGeoCommandQueue(&geocmd);
235 
236  int n = 0;
237  GEO_Primitive *prim;
239  {
240  primid(n) = (int)prim->getMapIndex();
241  procid(n) = (exint)prim->getMapIndex();
242 
243  n++;
244 
245  if (n >= chunksize)
246  {
247  processVexBlock(context, rundata, argc, argv, primid.array(), n, t);
248  n = 0;
249  }
250  }
251 
252  // Handle any trailing values.
253  if (n)
254  processVexBlock(context, rundata, argc, argv, primid.array(), n, t);
255 
256  // If multithreaded, the following is done *after*
257  // all threads have joined.
258  // One does a fast merge like this:
259 /*
260  GVEX_GeoCommand allcmd;
261  for (int i = 0; i < numthreads; i++)
262  {
263  allcmd.appendQueue( threadcmds[i] );
264  }
265  allcmd.apply(gdp);
266 */
267  // Note that merging will steal data from the various thread queues,
268  // so the thread queues must be kept around until the application
269  // is complete.
270 
271  // In this example we are just doing single threading so we
272  // have but a single queue:
274  allcmd.appendQueue(geocmd);
275 
276  // NOTE: This manages data IDs for any modifications it does.
277  allcmd.apply(gdp);
278 
279  if (context.getVexErrors().isstring())
280  addError(SOP_VEX_ERROR, (const char *)context.getVexErrors());
281  if (context.getVexWarnings().isstring())
282  addWarning(SOP_VEX_ERROR, (const char *)context.getVexWarnings());
283 }
284 
285 namespace HDK_Sample {
287 {
288 public:
289  const static int NUM_BUFFERS = 2;
290  const static int INPUT_BUFFER = 0;
291  const static int OUTPUT_BUFFER = 1;
292 
294  {
295  clear();
296  }
298  {
299  clear();
300  myName.harden(name);
301  myType = type;
302  }
304  {
305  clear();
306  *this = src;
307  }
308 
309  void clear()
310  {
311  myType = CVEX_TYPE_INVALID;
312  for (int i = 0; i < NUM_BUFFERS; i++)
313  {
314  myBuffer[i] = 0;
315  myBufLen[i] = 0;
316  }
317  }
318 
320  {
321  myName.harden(src.name());
322  myType = src.type();
323 
324  for (int i = 0; i < NUM_BUFFERS; i++)
325  {
326  delete [] myBuffer[i];
327  myBufLen[i] = src.myBufLen[i];
328  myBuffer[i] = 0;
329  if (src.buffer(i) && src.myBufLen[i])
330  {
331  myBuffer[i] = new char[myBufLen[i]];
332  memcpy(myBuffer[i], src.buffer(i), src.myBufLen[i]);
333  }
334  }
335 
336  return *this;
337  }
338 
340  {
341  for (int i = 0; i < NUM_BUFFERS; i++)
342  {
343  delete [] myBuffer[i];
344  }
345  }
346 
347  void allocateBuffer(int bufnum, int n)
348  {
349  delete [] myBuffer[bufnum];
350  switch (myType)
351  {
352  case CVEX_TYPE_INTEGER:
353  myBuffer[bufnum] = new char [sizeof(int) * n];
354  break;
355  case CVEX_TYPE_FLOAT:
356  myBuffer[bufnum] = new char [sizeof(float) * n];
357  break;
358  case CVEX_TYPE_VECTOR3:
359  myBuffer[bufnum] = new char [3*sizeof(float) * n];
360  break;
361  case CVEX_TYPE_VECTOR4:
362  myBuffer[bufnum] = new char [4*sizeof(float) * n];
363  break;
364  default:
365  UT_ASSERT(0);
366  break;
367  }
368  myBufLen[bufnum] = n;
369  }
370 
371  void marshallIntoBuffer(int bufnum, GU_Detail *gdp, int *primid, int n)
372  {
373  allocateBuffer(bufnum, n);
374 
375  const GA_Attribute *attrib = gdp->findPrimitiveAttribute(name());
376  if (attrib)
377  {
378  switch (myType)
379  {
380  case CVEX_TYPE_INTEGER:
381  {
382  GA_ROHandleI handle(attrib);
383  for (int i = 0; i < n; i++)
384  {
385  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
386  ((int *)myBuffer[bufnum])[i] = handle.get(primoff);
387  }
388  break;
389  }
390  case CVEX_TYPE_FLOAT:
391  {
392  GA_ROHandleF handle(attrib);
393  for (int i = 0; i < n; i++)
394  {
395  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
396  ((float *)myBuffer[bufnum])[i] = handle.get(primoff);
397  }
398  break;
399  }
400  case CVEX_TYPE_VECTOR3:
401  {
402  GA_ROHandleV3 handle(attrib);
403  for (int i = 0; i < n; i++)
404  {
405  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
406  ((UT_Vector3 *)myBuffer[bufnum])[i] = handle.get(primoff);
407  }
408  break;
409  }
410  case CVEX_TYPE_VECTOR4:
411  {
412  GA_ROHandleV4 handle(attrib);
413  for (int i = 0; i < n; i++)
414  {
415  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
416  ((UT_Vector4 *)myBuffer[bufnum])[i] = handle.get(primoff);
417  }
418  break;
419  }
420  default:
421  {
422  UT_ASSERT(0);
423  break;
424  }
425  }
426  }
427  }
428 
429  void marshallDataToGdp(int bufnum, GU_Detail *gdp, int *primid, int n, int inc)
430  {
431  GA_Attribute *attrib = gdp->findPrimitiveAttribute(name());
432  if (attrib)
433  {
434  switch (myType)
435  {
436  case CVEX_TYPE_INTEGER:
437  {
438  GA_RWHandleI handle(attrib);
439  for (int i = 0, src = 0; i < n; i++, src += inc)
440  {
441  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
442  handle.set(primoff, ((int *)myBuffer[bufnum])[src]);
443  }
444  break;
445  }
446  case CVEX_TYPE_FLOAT:
447  {
448  GA_RWHandleF handle(attrib);
449  for (int i = 0, src = 0; i < n; i++, src += inc)
450  {
451  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
452  handle.set(primoff, ((float *)myBuffer[bufnum])[src]);
453  }
454  break;
455  }
456  case CVEX_TYPE_VECTOR3:
457  {
458  GA_RWHandleV3 handle(attrib);
459  for (int i = 0, src = 0; i < n; i++, src += inc)
460  {
461  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
462  handle.set(primoff, ((UT_Vector3 *)myBuffer[bufnum])[src]);
463  }
464  break;
465  }
466  case CVEX_TYPE_VECTOR4:
467  {
468  GA_RWHandleV4 handle(attrib);
469  for (int i = 0, src = 0; i < n; i++, src += inc)
470  {
471  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
472  handle.set(primoff, ((UT_Vector4 *)myBuffer[bufnum])[src]);
473  }
474  break;
475  }
476  default:
477  {
478  UT_ASSERT(0);
479  break;
480  }
481  }
482  // We've modified the attribute, so its data ID should be bumped.
483  attrib->bumpDataId();
484  }
485  }
486 
487  const char *name() const { return myName; };
488  CVEX_Type type() const { return myType; }
489  const char *buffer(int bufnum) const { return myBuffer[bufnum]; }
490  char *buffer(int bufnum) { return myBuffer[bufnum]; }
491 
492 private:
493  UT_String myName;
494  CVEX_Type myType;
495  char *myBuffer[NUM_BUFFERS];
496  int myBufLen[NUM_BUFFERS];
497 };
498 }
499 
500 void
502  CVEX_RunData &rundata,
503  int argc, char **argv,
504  int *primid, int n,
505  fpreal t)
506 {
507  // We always export our primitive ids, so bind as integer.
508  context.addInput("primid", CVEX_TYPE_INTEGER, primid, n);
509 
510  // These are lazy evaluated since we don't want to pay
511  // the cost if not needed.
512  context.addInput("P", // Name of parameter
513  CVEX_TYPE_VECTOR3, // VEX Type
514  true); // Is varying?
515 
516  // We lazy add our time dependent inputs as we only want to
517  // flag time dependent if they are used.
518  context.addInput("Time", CVEX_TYPE_FLOAT, false);
519  context.addInput("TimeInc", CVEX_TYPE_FLOAT, false);
520  context.addInput("Frame", CVEX_TYPE_FLOAT, false);
521 
522  // Lazily bind all of our primitive attributes.
523  UT_Array<sop_bindparms> bindlist;
525  !it.atEnd();
526  ++it)
527  {
529 
530  GA_Attribute *attrib = it.attrib();
531  if( attrib->getStorageClass() == GA_STORECLASS_FLOAT &&
532  attrib->getTupleSize() < 3 )
533  {
534  type = CVEX_TYPE_FLOAT;
535  }
536  else if( attrib->getStorageClass() == GA_STORECLASS_FLOAT &&
537  attrib->getTupleSize() < 4 )
538  {
539  type = CVEX_TYPE_VECTOR3;
540  }
541  else if( attrib->getStorageClass() == GA_STORECLASS_FLOAT )
542  {
543  type = CVEX_TYPE_VECTOR4;
544  }
545  else if( attrib->getStorageClass() == GA_STORECLASS_INT )
546  {
547  type = CVEX_TYPE_INTEGER;
548  }
549  else
550  {
551  type = CVEX_TYPE_INVALID;
552  }
553 
554  if (type == CVEX_TYPE_INVALID)
555  continue;
556 
557  context.addInput(attrib->getName(), type, true);
558 
559  bindlist.append( sop_bindparms(attrib->getName(),
560  type) );
561  }
562 
563  // We want to evaluate at the context time, not at what
564  // the global frame time happens to be.
565  rundata.setTime(t);
566 
567  // Load our array.
568  if (!context.load(argc, argv))
569  return;
570 
571  // Check for lazily bound inputs
573  CVEX_Value *var;
574  var = context.findInput("P", CVEX_TYPE_VECTOR3);
575  if (var)
576  {
577  P.setSize(n);
578  for (int i = 0; i < n; i++)
579  {
580  GA_Offset primoff = gdp->primitiveOffset(GA_Index(primid[i]));
581  P(i) = gdp->getGEOPrimitive(primoff)->baryCenter();
582  }
583  var->setTypedData(P.array(), n);
584  }
585 
586  // Check if any of our parameters exist as either inputs or outputs.
587  for (exint j = 0; j < bindlist.entries(); j++)
588  {
589  var = context.findInput(bindlist(j).name(), bindlist(j).type());
590  if (var)
591  {
592  // This exists as an input, we have to marshall it.
593  bindlist(j).marshallIntoBuffer(sop_bindparms::INPUT_BUFFER,
594  gdp, primid, n);
595  void *buf = (void *)bindlist(j).buffer(sop_bindparms::INPUT_BUFFER);
596  var->setRawData(bindlist(j).type(), buf, n);
597  }
598 
599  // The same attribute may be both an input and an output
600  // This results in different CVEX_Values so requires two
601  // buffers in the bindings.
602  if ((var = context.findOutput(bindlist(j).name(), bindlist(j).type())))
603  {
604  bindlist(j).allocateBuffer(sop_bindparms::OUTPUT_BUFFER, n);
605  void *buf = (void *)bindlist(j).buffer(sop_bindparms::OUTPUT_BUFFER);
606  if (var->isVarying())
607  var->setRawData(bindlist(j).type(), buf, n);
608  else
609  var->setRawData(bindlist(j).type(), buf, 1);
610  }
611 
612  }
613 
614  // Compute the time dependent inputs.
615  fpreal32 curtime, curtimeinc, curframe;
616 
617  var = context.findInput("Time", CVEX_TYPE_FLOAT);
618  if (var)
619  {
620  OP_Node::flags().setTimeDep(true);
621 
622  curtime = t;
623 
624  var->setTypedData(&curtime, 1);
625  }
626  var = context.findInput("TimeInc", CVEX_TYPE_FLOAT);
627  if (var)
628  {
629  OP_Node::flags().setTimeDep(true);
630 
631  curtimeinc = 1.0f/OPgetDirector()->getChannelManager()->getSamplesPerSec();
632 
633  var->setTypedData(&curtimeinc, 1);
634  }
635  var = context.findInput("Frame", CVEX_TYPE_FLOAT);
636  if (var)
637  {
638  OP_Node::flags().setTimeDep(true);
639 
640  curframe = OPgetDirector()->getChannelManager()->getSample(t);
641 
642  var->setTypedData(&curframe, 1);
643  }
644 
645  // clear flag to detect time dependence of ch expressions.
646  rundata.setTimeDependent(false);
647 
648  // Actually execute the vex code!
649  // Allow interrupts.
650  context.run(n, true, &rundata);
651 
652  // Update our timedependency based on the flag
653  if (rundata.isTimeDependent())
654  OP_Node::flags().setTimeDep(true);
655 
656  // Write out all bound parameters.
657  for (exint j = 0; j < bindlist.entries(); j++)
658  {
659  var = context.findOutput(bindlist(j).name(), bindlist(j).type());
660  if (var)
661  {
662  bindlist(j).marshallDataToGdp(sop_bindparms::OUTPUT_BUFFER, gdp, primid, n, (var->isVarying() ? 1 : 0));
663  }
664  }
665 }
666 
667 void
669 {
670  UT_String shoppath;
671  int vexsrc = VEXSRC(t);
672 
673  script = "";
674 
675  switch (vexsrc)
676  {
677  case 0:
678  {
679  getFullPath(shoppath);
680  script = "op:";
681  script += shoppath;
682  // buildVexCommand appends to our script variable.
684  break;
685  }
686 
687  case 2:
688  // Straightforward, use the explicit script
689  SCRIPT(script, t);
690  break;
691 
692  case 1:
693  {
694  SHOPPATH(shoppath, t);
695 
696  // Use the referenced shop network.
697  SHOP_Node *shop;
698  shop = findSHOPNode(shoppath);
699  if (shop)
700  {
701  shop->buildVexCommand(script, shop->getSpareParmTemplates(), t);
703 
704  // It is possible that we are dealing with a multi-context
705  // shader (ie, shop). In that case, we need to specify the
706  // shader context which we want to interpret it as. This is done
707  // by passing it as an argument. Since this operator invokes
708  // CVEX shader, we specify that type. Single-context shaders
709  // will ignore it.
710  shop->buildShaderString(script, t, 0, 0, 0, SHOP_CVEX);
711  }
712  break;
713  }
714  }
715 }
716 
717 bool
719 {
720  if (myCodeGenerator.getVariableString(index, value))
721  return true;
722  // else delegate to base class
723  return SOP_Node::evalVariableValue(value, index, thread);
724 }
725 
728 {
730 }
731 
734 {
735  return &myCodeGenerator;
736 }
737 
738 bool
740 {
741  return myCodeGenerator.hasShaderParameter(parm_name);
742 }
743 
744 const char *
746 {
747  return VOP_OPTYPE_NAME;
748 }
749 
752 {
753  return VOP_OPTYPE_ID;
754 }
755 
756 void
758 {
759  int update_id = myCodeGenerator.beginUpdate();
760  SOP_Node::opChanged(reason, data);
761  myCodeGenerator.ownerChanged(reason, data);
762  myCodeGenerator.endUpdate(update_id);
763 }
764 
765 void
767 {
769  SOP_Node::finishedLoadingNetwork(is_child_call);
770 }
771 
772 void
773 SOP_PrimVOP::addNode(OP_Node *node, int notify, int explicitly)
774 {
776  SOP_Node::addNode(node, notify, explicitly);
778 }
779 
780 void
782  OP_NodeInfoParms &iparms)
783 {
784  SOP_Node::getNodeSpecificInfoText(context, iparms);
785 
786 #if 0
787  // Compile errors should be already automatically reported in the
788  // node specific info. Still, here is an example of how that can be done
789  // explicitly.
790  UT_String errors;
791  if( myCodeGenerator.getCompilerErrors( errors ))
792  {
793  iparms.appendSeparator();
794  iparms.append(errors);
795  }
796 #endif
797 }
798 
void endUpdate(int update_level)
static PRM_Name theVopCompilerName
SYS_FORCE_INLINE void bumpDataId()
Definition: GA_Attribute.h:306
static PRM_SpareData shopCVEX
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
Definition of a geometry attribute.
Definition: GA_Attribute.h:198
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:2540
void afterAddNode(OP_Node *node)
PRM_API const PRM_Type PRM_CALLBACK
virtual UT_Vector3 baryCenter() const
bool evalVariableValue(fpreal &val, int index, int thread) override
virtual OP_ERROR error()
OP_ERROR cookMySop(OP_Context &context) override
Definition: SOP_PrimVOP.C:146
void addNode(OP_Node *node, int notify=1, int explicitly=1) override
Definition: SOP_PrimVOP.C:773
bool evalVariableValue(UT_String &value, int index, int thread) override
Code generation variables.
Definition: SOP_PrimVOP.C:718
bool addInput(const UT_StringHolder &name, CVEX_Type type, bool varying)
PRM_API const PRM_Type PRM_STRING
const OP_NodeFlags & flags() const
Definition: OP_Node.h:1388
DEP_ContextOptionsReadHandle getContextOptions() const
Definition: OP_Context.h:122
OP_ERROR lock(OP_Context &context)
Locks all inputs.
int getTupleSize() const
Size of the AIFTuple, if it exists. If it doesn't, 1.
const PRM_Template * getSpareParmTemplates() const
fpreal getTime() const
Definition: OP_Context.h:62
const char * getChildType() const override
Definition: SOP_PrimVOP.C:745
void beforeAddNode(OP_Node *node)
SYS_FORCE_INLINE bool atEnd() const
VOP_CodeGenerator * getVopCodeGenerator() override
Definition: SOP_PrimVOP.C:733
OP_Channels * getChannels() const
void opChanged(OP_EventType reason, void *data=0) override
We need special alerts now that we contain VOPs.
Definition: SOP_PrimVOP.C:757
int64 exint
Definition: SYS_Types.h:125
PRM_API const PRM_Type PRM_ORD
SOP_PrimVOP(OP_Network *net, const char *, OP_Operator *entry)
Definition: SOP_PrimVOP.C:119
virtual void finishedLoadingNetwork(bool is_child_call=false)
bool isVarying() const
Query whether the VEX value is uniform or varying.
Definition: CVEX_Value.h:76
void setTimeDependent(bool v)
Definition: CVEX_Context.h:145
UT_ErrorSeverity
Definition: UT_Error.h:25
T * array()
Definition: UT_Array.h:819
Parameters for OP_Node::getInfoText()/OP_Node::getNodeSpecificInfoText()
bool setRawData(CVEX_Type type, void *data, int array_size)
Type unsafe way of setting VEX data. Avoid using if possible.
const CVEX_ValueT< PREC > * findOutput(const UT_StringRef &name, CVEX_Type type) const
Find an output by name/type.
Definition: CVEX_Context.h:340
**But if you need a or simply need to know when the task has note that the like this
Definition: thread.h:617
static PRM_Name theVopForceCompileName
virtual bool hasShaderParameter(const char *parm_name)
bool addOperator(OP_Operator *op, std::ostream *err=nullptr)
static const char * theChildTableName
Definition: SOP_PrimVOP.h:80
int void appendSeparator()
Append a section separator.
float fpreal32
Definition: SYS_Types.h:200
bool getVariableString(int index, UT_String &value)
void addError(int code, const char *msg=0)
Definition: SOP_Node.h:1158
void setSize(exint newsize)
Definition: UT_Array.h:666
SYS_FORCE_INLINE iterator begin(GA_AttributeScope scope=GA_SCOPE_INVALID) const
static bool forceCompile(OP_Node *node)
const char * buffer(int bufnum) const
Definition: SOP_PrimVOP.C:489
CH_Manager * getChannelManager()
Definition: OP_Director.h:113
void opChanged(OP_EventType reason, void *data=0) override
SYS_FORCE_INLINE const UT_StringHolder & getName() const
Definition: GA_Attribute.h:283
SYS_FORCE_INLINE GEO_Primitive * getGEOPrimitive(GA_Offset primoff)
Definition: GEO_Detail.h:1177
GA_Size GA_Offset
Definition: GA_Types.h:641
A class representing a VEX value.
Definition: CVEX_Value.h:60
bool setTypedData(VEXint< PREC > *data, int array_size)
static PRM_Template myTemplateList[]
Definition: SOP_PrimVOP.h:53
OP_OperatorFilter * getOperatorFilter()
GLdouble n
Definition: glcorearb.h:2008
CVEX_Type type() const
Definition: SOP_PrimVOP.C:488
bool isTimeDependent() const
Definition: CVEX_Context.h:84
CH_Manager * CHgetManager()
Definition: CH_Manager.h:2079
fpreal getSample(fpreal t) const
Definition: CH_Manager.h:1214
void SCRIPT(UT_String &s, fpreal t)
Definition: SOP_PrimVOP.h:96
void allocateBuffer(int bufnum, int n)
Definition: SOP_PrimVOP.C:347
void addWarning(SOP_ErrorCodes code, const char *msg=0)
Definition: SOP_Node.h:1164
fpreal getSamplesPerSec() const
Definition: CH_Manager.h:1178
GA_StorageClass getStorageClass() const
Returns the approximate type of the attribute.
const CVEX_ValueT< PREC > * findInput(const UT_StringRef &name, CVEX_Type type) const
Find an input by name/type.
Definition: CVEX_Context.h:318
void setTime(fpreal time)
Definition: CVEX_Context.h:50
void finishedLoadingNetwork(bool is_child_call=false) override
VOP and VEX functions.
Definition: SOP_PrimVOP.C:766
const DEP_ContextOptionsStack * getContextOptionsStack() const
Return the options associated with the calling context.
Definition: OP_Caller.h:44
void SHOPPATH(UT_String &path, fpreal t)
Definition: SOP_PrimVOP.h:99
char * buffer(int bufnum)
Definition: SOP_PrimVOP.C:490
bool hasVexShaderParameter(const char *parm_name) override
Definition: SOP_PrimVOP.C:739
sop_bindparms(const sop_bindparms &src)
Definition: SOP_PrimVOP.C:303
void harden()
Take shallow copy and make it deep.
Definition: UT_String.h:215
virtual bool buildShaderString(UT_String &result, fpreal now, const UT_Options *options, OP_Node *obj=0, OP_Node *sop=0, SHOP_TYPE interpret_type=SHOP_INVALID)
void ownerChanged(OP_EventType reason, void *data)
bool run(int array_size, bool interruptable, CVEX_RunDataT< PREC > *rundata=nullptr)
SOP_NodeFlags mySopFlags
Definition: SOP_Node.h:1625
#define GA_FOR_ALL_PRIMITIVES(gdp, prim)
Definition: GA_GBMacros.h:36
void setProcId(exint *procid)
Definition: CVEX_Context.h:109
OP_OpTypeId
Definition: OP_OpTypeId.h:18
SYS_FORCE_INLINE T get(GA_Offset off, int comp=0) const
Definition: GA_Handle.h:203
UT_StringHolder getFullPath() const
Definition: PRM_ParmOwner.h:64
GLuint const GLchar * name
Definition: glcorearb.h:786
GA_Size GA_Index
Define the strictness of GA_Offset/GA_Index.
Definition: GA_Types.h:635
CVEX_Type
The CVEX_Type enum defines the VEX types available to CVEX.
Definition: CVEX_Value.h:29
PRM_API const PRM_Type PRM_COMMAND
GLenum GLenum GLsizei void * table
Definition: glad.h:5129
void executeVex(int argc, char **argv, fpreal t, OP_Caller &opcaller)
Definition: SOP_PrimVOP.C:192
void setManagesDataIDs(bool onOff)
Definition: SOP_NodeFlags.h:36
exint append()
Definition: UT_Array.h:142
GLdouble t
Definition: glad.h:2397
int buildVexCommand(UT_String &result, const PRM_Template *templatelist, fpreal now, int start_parm=0, int end_parm=INT_MAX, bool use_parmvop_tag=true)
GU_Detail * gdp
Definition: SOP_Node.h:1622
SYS_FORCE_INLINE const GA_Attribute * findPrimitiveAttribute(GA_AttributeScope s, const UT_StringRef &name) const
Definition: GA_Detail.h:1048
sop_bindparms & operator=(const sop_bindparms &src)
Definition: SOP_PrimVOP.C:319
exint entries() const
Alias of size(). size() is preferred.
Definition: UT_Array.h:648
void getNodeSpecificInfoText(OP_Context &context, OP_NodeInfoParms &parms) override
Definition: SOP_PrimVOP.C:781
static CH_LocalVariable theLocalVariables[]
GLint j
Definition: glad.h:2733
static OP_Node * myConstructor(OP_Network *net, const char *name, OP_Operator *entry)
Definition: SOP_PrimVOP.C:113
SYS_FORCE_INLINE GA_Size getNumVertices() const
Return the number verticies in the entire detail.
Definition: GA_Detail.h:504
**Note that the tasks the is the thread number *for the or if it s being executed by a non pool thread(this *can happen in cases where the whole pool is occupied and the calling *thread contributes to running the work load).**Thread pool.Have fun
SYS_FORCE_INLINE GA_Index getMapIndex() const
Gets the index of this primitive in the detail containing it.
Definition: GA_Primitive.h:151
#define VOP_TABLE_NAME
Definition: OP_Node.h:250
virtual void addNode(OP_Node *node, int notify=1, int explicitly=1)
void setGeoCommandQueue(VEX_GeoCommandQueue< PREC > *geocmd)
Sets the command queue for this context.
Definition: CVEX_Context.h:116
Push & restore the evaluation time (and optionally a channel collection)
Definition: CH_Manager.h:1908
const char * name() const
Definition: SOP_PrimVOP.C:487
SYS_API int SYSgetSTID()
virtual void addExtraInput(OP_Node *op, OP_InterestType type)
SYS_FORCE_INLINE void set(GA_Offset off, const T &val) const
Definition: GA_Handle.h:354
void setTimeDep(bool on_off)
Definition: OP_NodeFlags.h:111
void marshallDataToGdp(int bufnum, GU_Detail *gdp, int *primid, int n, int inc)
Definition: SOP_PrimVOP.C:429
fpreal64 fpreal
Definition: SYS_Types.h:277
#define VOP_OPTYPE_NAME
Definition: OP_Node.h:296
SYS_FORCE_INLINE GA_Offset primitiveOffset(GA_Index index) const
Given a primitive's index (in append order), return its data offset.
Definition: GA_Detail.h:419
SYS_FORCE_INLINE const GA_AttributeDict & primitiveAttribs() const
Definition: GEO_Detail.h:1943
OP_API OP_Director * OPgetDirector()
GLuint index
Definition: glcorearb.h:786
void newSopOperator(OP_OperatorTable *table)
Definition: SOP_PrimVOP.C:57
sop_bindparms(const char *name, CVEX_Type type)
Definition: SOP_PrimVOP.C:297
SYS_FORCE_INLINE GA_Size getNumPrimitives() const
Return the number of primitives.
Definition: GA_Detail.h:408
const DEP_ContextOptionsStack * getContextOptionsStack() const
Definition: OP_Context.h:120
OP_EventType
Definition: OP_Value.h:22
Per-run data for CVEX execution.
Definition: CVEX_Context.h:38
DEP_ContextOptionsReadHandle getContextOptions() const
Return the options associated with the calling context.
Definition: OP_Caller.h:48
SHOP_Node * findSHOPNode(const char *path) const
Definition: OP_Node.h:558
static const int INPUT_BUFFER
Definition: SOP_PrimVOP.C:290
bool isstring() const
Definition: UT_String.h:691
void append(const char *string)
Append a string to the text buffer.
#define UT_ASSERT(ZZ)
Definition: UT_Assert.h:156
Definition: core.h:1131
void marshallIntoBuffer(int bufnum, GU_Detail *gdp, int *primid, int n)
Definition: SOP_PrimVOP.C:371
int parse(char *argv[], int max_args, const char *quotes="\"'", bool keep_quotes=false)
Definition: UT_String.h:803
void setOpCaller(UT_OpCaller *caller)
Definition: CVEX_Context.h:74
bool load(int argc, const char *const argv[])
void ownerFinishedLoadingNetwork()
const UT_String & getVexWarnings() const
OP_OpTypeId getChildTypeID() const override
Definition: SOP_PrimVOP.C:751
OP_OperatorFilter * getOperatorFilter() override
Overriding these are what allow us to contain VOPs.
Definition: SOP_PrimVOP.C:727
Call VEX from C++.
Definition: CVEX_Context.h:203
type
Definition: core.h:1059
void processVexBlock(CVEX_Context &context, CVEX_RunData &rundata, int argc, char **argv, int *primid, int n, fpreal t)
Definition: SOP_PrimVOP.C:501
const UT_String & getVexErrors() const
static PRM_Default theVopCompilerVexDefault
void getNodeSpecificInfoText(OP_Context &context, OP_NodeInfoParms &iparms) override
VOP_CodeGenerator myCodeGenerator
Definition: SOP_PrimVOP.h:135
int VEXSRC(fpreal t)
Definition: SOP_PrimVOP.h:94
Definition: format.h:895
static const int NUM_BUFFERS
Definition: SOP_PrimVOP.C:289
static const int OUTPUT_BUFFER
Definition: SOP_PrimVOP.C:291
void buildScript(UT_String &script, fpreal t)
Definition: SOP_PrimVOP.C:668
void appendQueue(VEX_GeoCommandQueue< PREC > &geocmd)
SYS_FORCE_INLINE GA_Size getNumPoints() const
Return the number of points.
Definition: GA_Detail.h:334
GLenum src
Definition: glcorearb.h:1793
OP_ERROR duplicateSource(unsigned index, OP_Context &context, GU_Detail *gdp, bool clean=true)