HDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CVEX_Context.h
Go to the documentation of this file.
1 /*
2  * PROPRIETARY INFORMATION. This software is proprietary to
3  * Side Effects Software Inc., and is not to be reproduced,
4  * transmitted, or disclosed in any way without written permission.
5  *
6  * NAME: CVEX_Context.h ( CVEX Library, C++)
7  *
8  * COMMENTS: C++ interface to VEX. This class defines a parameter to the
9  * VEX function.
10  */
11 
12 #ifndef __CVEX_Context__
13 #define __CVEX_Context__
14 
15 #include "CVEX_API.h"
16 #include "CVEX_Function.h"
17 #include "CVEX_ValueList.h"
18 #include "CVEX_Transform.h"
19 #include <VEX/VEX_PodTypes.h>
20 #include <UT/UT_NonCopyable.h>
21 #include <UT/UT_UniquePtr.h>
22 
23 template <VEX_Precision PREC> class cvex_RunData;
24 class UT_OpCaller;
25 template <VEX_Precision PREC> class VEX_AutoInstance;
26 template <VEX_Precision PREC> class VEX_AutoFoldedCode;
27 template <VEX_Precision PREC> class VEX_Instance;
28 class VEX_GeoInputs;
29 template <VEX_Precision PREC> class VEX_GeoCommandQueue;
30 class VEX_ChannelCache;
31 class VEX_FileCache;
32 
33 /// @brief Per-run data for CVEX execution
34 ///
35 /// This class is used to set and retrieve data specific to an individual
36 /// execution run using CVEX_Context::run().
37 template <VEX_Precision PREC>
39 {
40 public:
41  CVEX_RunDataT();
42  ~CVEX_RunDataT();
43 
44  /// Resets the run data for re-use.
45  void clear();
46 
47  /// Set the evaluation time. This is what will be used by op: references
48  /// triggered by VEX commands like volumesample. If not set, the current
49  /// channel time is used instead (if an OP_Director is available).
51  {
52  myTimeSpecified = true;
53  myTransform.setTime(time);
54  }
55 
56  /// Sets the operator working directory. This is used by ch()
57  /// style vex functions to determine where the relative path for
58  /// path resolution should be.
59  /// Use OP_Node::getUniqueId() to pass this in.
60  void setCWDNodeId(int id)
61  {
62  myTransform.setCwdId(id);
63  }
64  /// The world id is the node which defines the transform space for the CWD.
65  /// If it's not defined the object containing the CWD will be used (or the
66  /// CWD if it's not part of an object network)
67  void setWorldNodeId(int id)
68  {
69  myTransform.setWorldId(id);
70  }
71 
72  /// Sets the OP callback. This is used to setup dependencies on any
73  /// referenced op: expressions. Can be applied to the context at any time.
74  void setOpCaller(UT_OpCaller *caller)
75  {
76  myTransform.setOpCaller(caller);
77  }
78 
79  /// Access to the OP_Caller
80  UT_OpCaller *getOpCaller() const { return myTransform.opCaller(); }
81 
82  /// Returns true when, after running the CVEX_Context, a ch() function
83  /// reported that it was time dependent.
84  bool isTimeDependent() const { return myTimeDependent; }
85 
86  /// Set flag indicating whether there are any time samples involved.
88  {
89  myTimeSampleEncountered = v;
90  }
91 
92  /// Returns true when, after running the CVEX_Context, a usd_attrib()
93  /// function reported that it has some time samples (values at time codes).
95  {
96  return myTimeSampleEncountered;
97  }
98 
99  /// Sets the geo input callback for controlling how opinput: references
100  /// are handled
101  void setGeoInputs(const VEX_GeoInputs *geo)
102  {
103  myGeoInputs = geo;
104  }
105  const VEX_GeoInputs *getGeoInputs() const { return myGeoInputs; }
106 
107  /// Sets the proc id array. Owned by the caller. Must be at least
108  /// the length of your size.
109  void setProcId(exint *procid)
110  {
111  myProcId = procid;
112  }
113  const exint *getProcId() const { return myProcId; }
114 
115  /// Sets the command queue for this context
117  {
118  myGeoCommandQueue = geocmd;
119  }
121  {
122  return myGeoCommandQueue;
123  }
124 
125  VEX_ChannelCache *getChannelCache() { return myChannelCache; }
126 
127  VEX_FileCache* getFileCache() { return myFileCache; }
128 
129  /// Every VEX function has a transform context associated with it. This
130  /// transform context is used by VEX functions like ptransform() to provide
131  /// ways to transform to other spaces (like "space:world" or
132  /// "space:object"). This method allows you to modify the transform
133  /// context of this shader.
134  CVEX_Transform &getTransform() { return myTransform; }
135 
136  /// @{
137  /// Accessors
138  bool timeSpecified() const { return myTimeSpecified; }
139  bool timeDependent() const { return myTimeDependent; }
140  int cwdId() const { return myTransform.cwdId(); }
141  int worldId() const { return myTransform.worldId();}
142  fpreal time() const { return myTransform.time(); }
143  /// @}
144  /// Set as time dependent flag
145  void setTimeDependent(bool v) { myTimeDependent = v; }
146 
147  /// Get the cached VEX_Instance, which can be reused for multiple runs
148  /// until clear() is called.
149  /// This ensures that local word data (e.g. geometry bindings) remain the
150  /// same between runs.
151  VEX_Instance<PREC> *getOrCreateInstance(
152  const VEX_AssemblePtr &assemble,
154 
155 private:
156  CVEX_Transform myTransform;
157  const VEX_GeoInputs *myGeoInputs;
158  VEX_GeoCommandQueue<PREC> *myGeoCommandQueue;
159  exint *myProcId;
160  bool myTimeSpecified;
161  bool myTimeDependent;
162  bool myTimeSampleEncountered;
163  VEX_ChannelCache *myChannelCache;
164  VEX_FileCache *myFileCache;
165 
166  // The VEX_AutoInstance depends on the lifetime of the VEX_Assemble and
167  // VEX_AutoFoldedCode.
168  VEX_AssemblePtr myAssemble;
171 };
172 
174 
177 
178 /// These methods return the meta count and unique id of the global
179 /// cvex function cache. This isn't for this particular context, thus
180 /// is static. If these change, all your contexts allocated before
181 /// will be invalid.
184 
186 {
187  PROBE_ERROR, // Shader hasn't been loaded or there were errors
188  NOT_ASSIGNED, // Variable is not assigned any value
189  CONSTANT_0, // Variable is always set to 0
190  CONSTANT_1, // Variable is always set to 1
191  CONSTANT_VALUE, // Variable is a constant value (not 0 or 1)
192  NOT_CONSTANT, // Variable is not-constant
193 };
194 
195 /// @brief Call VEX from C++
196 ///
197 /// The CVEX_Context class provides the main interface to let C++ code call VEX
198 /// to perform computations. This allows users to modify algorithms by
199 /// performing computations in VEX.
200 /// - VEX automatically takes advantage of SSE
201 /// - VEX can perform run-time optimization
202 template <VEX_Precision PREC>
204 {
205 public:
206  CVEX_ContextT();
207  ~CVEX_ContextT();
208 
209  /// clearing the context will allow you to set up the input and output
210  /// parameters again.
211  /// @note load() must be called again before you can run the VEX code.
212  void clear();
213 
214  /// calling clearAllFunctions() will force all CVEX object code to be
215  /// flushed out of memory and to be reloaded. Be cautioned that this may
216  /// have side-effects, and should only be called at a safe time.
217  /// @note This will also cause *all* functions to be cleared (see clear()).
218  static void clearAllFunctions();
219 
220  /// Removes the given function from the CVEX context.
221  static void clearFunction(const UT_StringRef &fn_name);
222 
223  /// This method will return true if the code referenced by the context has
224  /// been deleted (see @clearAllFunctions()). If you've cached a
225  /// CVEX_Context, then this can be used to see if it's still valid.
226  bool isValid() const;
227 
228  /// Add possible input parameters to the function. These are parameters
229  /// whose values are overridden by values you pass in. If the user's VEX
230  /// function has these parameters the C++ code should assign the values
231  /// after calling load(), but before calling run().
232  ///
233  /// Calling this version of addInput() allows you to defer computing the
234  /// value of the variable until you know whether it will actually be used
235  /// by the VEX function.
236  bool addInput(const UT_StringHolder &name,
237  CVEX_Type type, bool varying);
238 
239  /// If you know the value beforehand, you can add the symbol and it's
240  /// value at the same time.
241  /// Note: The data is referenced, not copied, so keep it live until after
242  /// run() has been called.
243  bool addInput(const UT_StringHolder &name,
244  CVEX_Type type,
245  void *data, int array_size);
246 
247  /// Adds a constant input. You should still maintain the reference
248  /// but the data may be constant folded into the assemble, so the
249  /// values *must* be set ahead of time and possibly will not update
250  /// if you change the original.
251  bool addConstantInput(const UT_StringHolder &name,
252  CVEX_Type type,
253  void *data, int array_size);
254  bool addConstantInput(const UT_StringHolder &name, CVEX_StringArray &strings);
255 
256  /// Add an "string <name>" input. An array length of 1 makes the variable
257  /// uniform.
258  /// Note: The strings are referenced, not copied, so keep it live until
259  /// after run() has been called.
260  bool addInput(const UT_StringHolder &name, CVEX_StringArray &strings);
261 
262  /// Add a required output. If no required output is specified, all
263  /// exports/outputs are computed.
264  /// Note: Due to the varying/uniform state of an output depending
265  /// significantly on the inputs' varying/uniform state -- and operations
266  /// performed -- then, unlike addInput, no storage can be allocated until
267  /// after load.
268  /// Note: If no storage is allocated, the output is still computed but
269  /// the result is thrown away.
270  bool addRequiredOutput(const UT_StringHolder &name, CVEX_Type type);
271 
272  /// Checks if the VEX function by the given name already exists.
273  bool hasFunction(const UT_StringRef &name) const;
274 
275  /// Load the definition of the VEX function.
276  /// Usually VEX functions are loaded from compiled VEX code stored
277  /// in files on the search path. But, callers can use this method to
278  /// define a VEX function from the stream.
279  /// The module name can be optionally overriden with a name argument (if
280  /// it's NULL, the name in the stream is used implicitly).
281  /// The final name of the module is returned in actual_name (if not NULL).
282  /// If override_old is true, if the old function by that name is found,
283  /// then it will be overriden and updated with the new one.
284  bool preloadFile(UT_IStream &is, const char *name,
285  UT_String *actual_name, bool override_old);
286 
287  /// Loads the given file. Instead of registering the loaded
288  /// function in the global function table, returns it as a CVEX_Function
289  CVEX_Function preloadFunction(UT_IStream &is);
290 
291  /// Loads the functin form the global function table.
292  CVEX_Function preloadGlobalFunction(const char *funcname);
293 
294  /// Load the VEX function.
295  /// Inputs must be specified @b before this function is called. After
296  /// loading, the input list will have flags set telling you whether the
297  /// input parameter is used. At this point, you should set the data for
298  /// all used inputs.
299  ///
300  /// The list of outputs will also be defined, meaning that you can figure
301  /// out what's going to be written by the VEX function.
302  bool load(int argc, const char *const argv[]);
303 
304  /// With load function we already have pre-loaded the CVEX_Function
305  /// so the argv[0] is ignored.
306  bool loadFunction(CVEX_Function function, int argc, const char *const argv[]);
307 
308  /// Quick test to see if the function has been loaded.
309  bool isLoaded() const;
310 
311  /// The list of input parameters to the function. It's possible that
312  /// these values may be shared between the input and output lists.
313  CVEX_ValueListT<PREC> &getInputList() { return myInputs; }
314  const CVEX_ValueListT<PREC> &getInputList() const { return myInputs; }
315 
316  /// Find an input by name/type.
317  const CVEX_ValueT<PREC> *findInput(const UT_StringRef &name, CVEX_Type type) const
318  { return myInputs.getValue(name, type); }
320  { return myInputs.getValue(name, type); }
321 
322  /// Find an input by name.
323  const CVEX_ValueT<PREC> *findInput(const UT_StringRef &name) const
324  { return myInputs.getValue(name, CVEX_TYPE_INVALID); }
326  { return myInputs.getValue(name, CVEX_TYPE_INVALID); }
327 
328  /// The list of output parameters from the function. After the function
329  /// has been run, the output parameters will have their values written to
330  /// by VEX.
331  ///
332  /// If the output has not had CVEX_Value::setData() called, then the data
333  /// will have been written to internal storage and can be retrieved calling
334  /// CVEX_Value::getData().
335  const CVEX_ValueListT<PREC> &getOutputList() const { return myOutputs; }
336  CVEX_ValueListT<PREC> &getOutputList() { return myOutputs; }
337 
338  /// Find an output by name/type.
339  const CVEX_ValueT<PREC> *findOutput(const UT_StringRef &name, CVEX_Type type) const
340  { return myOutputs.getValue(name, type); }
342  { return myOutputs.getValue(name, type); }
343 
344  /// Find and output by name.
345  const CVEX_ValueT<PREC> *findOutput(const UT_StringRef &name) const
346  { return myOutputs.getValue(name, CVEX_TYPE_INVALID); }
348  { return myOutputs.getValue(name, CVEX_TYPE_INVALID); }
349 
350  /// Query the assignment status of an output. This must be called after
351  /// the code has been loaded.
352  CVEX_ProbeResult probeOutput(const UT_StringRef &name,
353  CVEX_Type type) const;
354 
355  /// Initializes the values array with the defaults of the given parameter.
356  /// Leaves values empty if it can't find the parameter.
357  void getParameterDefaults(const UT_StringRef &name,
358  CVEX_Type ctype,
359  UT_DoubleArray &values) const;
360 
361  /// Run the VEX function given a list of input variables and a list of
362  /// output parameters. Each input/output parameter under your control
363  /// should have an array size of either 1 or at least the array_size given
364  /// to the run() method. It's possible to run on fewer array elements
365  /// than have been allocated, but an error will be returned if there are
366  /// input parameters which don't have enough allocation.
367  ///
368  /// Pass in true for interruptable when running from within Houdini.
369  ///
370  /// The run() function may be called multiple times, provided that the
371  /// input parameters don't change. So, if you need to evaluate the data
372  /// in chunks, you can do this by re-initializing the input parameter data
373  /// between calls to run(). However, you should not change the
374  /// uniform/varying state of any input parameters without doing a re-load
375  /// of the VEX function.
376  /// @param array_size The size of varying arrays. All varying arrays must
377  /// be this size.
378  /// @param interruptable If true, VEX will check the state of the
379  /// UT_Interrupt. This should be enabled when called from within
380  /// Houdini. If interruptable is false, then the user will @b not be
381  /// able to break out of endless loops in VEX. It's better to leave it
382  /// true if you are unsure.
383  /// @param rundata Data that matches the precision PREC.
384  bool run(int array_size, bool interruptable,
385  CVEX_RunDataT<PREC> *rundata = nullptr);
386 
387  /// If load() or run() return false, this will return the error that
388  /// triggered the CVEX failure. Note that this is distinct from errors
389  // and warnings occurring when running VEX.
390  const char *getLastError() const { return myError; }
391 
392  /// If load() or run() failed or reported warnings, these methods will
393  /// return the errors reported by VEX.
394  /// {
395  const UT_String &getVexErrors() const;
396  const UT_String &getVexWarnings() const;
397  /// }
398 
399  /// Clear the errors reported by getVexErrors() / getVexWarnings().
400  void clearVexErrors();
401 
402  /// Add Constant Integer 32 Arrays
403  bool addConstantInput(const UT_StringHolder &name, UT_PackedArrayOfArrays<VEXint<PREC> > &intdata);
404 
405 private:
406  struct cvex_BoundValue
407  {
408  cvex_BoundValue()
409  : myValue(nullptr)
410  , myBindPtr(nullptr)
411  , myStoragePtr(nullptr)
412  {}
413  CVEX_ValueT<PREC>*myValue;
414  void *myBindPtr;
415  void *myStoragePtr;
416  };
417 
418  bool validateValue(const CVEX_ValueT<PREC> &value,
419  VEX_Instance<PREC> &state, int nproc);
420  void copyBoundData(cvex_BoundValue &bound,
421  VEX_Instance<PREC> &state,
422  int start, int nproc);
423  bool bindValues(UT_Array<cvex_BoundValue> &bound_vals,
424  VEX_Instance<PREC> &state, int nproc);
425  void extractStrings(CVEX_ValueT<PREC> &value,
426  VEX_Instance<PREC> &state,
427  int start, int nproc);
428  void extractDicts(CVEX_ValueT<PREC> &value,
429  VEX_Instance<PREC> &state,
430  int start, int nproc);
431  void extractArrays(CVEX_ValueT<PREC> &value,
432  VEX_Instance<PREC> &state,
433  int start, int nproc);
434  void extractUniform(CVEX_ValueT<PREC> &value,
435  VEX_Instance<PREC> &state);
436 
437  bool loadPrivate(const VEX_AssemblePtr &as,
438  int argc, const char *const argv[]);
439 
440  CVEX_ValueListT<PREC> myInputs;
441  CVEX_ValueListT<PREC> myOutputs;
443  UT_String myError;
444 
445  UT_Array<cvex_BoundValue> myBoundVals;
446 
447  UT_Array<VEXint<PREC>*> &getTempI() { myTempI.clear(); return myTempI; }
448  UT_Array<VEXfloat<PREC>*> &getTempF() { myTempF.clear(); return myTempF; }
449 
450  UT_Array<VEXfloat<PREC>*> myTempF;
451  UT_Array<VEXint<PREC>*> myTempI;
452 };
453 
455 
458 
459 #endif
const char * getLastError() const
Definition: CVEX_Context.h:390
CVEX_ValueListT< PREC > & getInputList()
Definition: CVEX_Context.h:313
const VEX_GeoInputs * getGeoInputs() const
Definition: CVEX_Context.h:105
VEX_ChannelCache * getChannelCache()
Definition: CVEX_Context.h:125
fpreal time() const
Definition: CVEX_Context.h:142
VEX_FileCache * getFileCache()
Definition: CVEX_Context.h:127
GT_API const UT_StringHolder time
CVEX_API exint CVEXgetGlobalContextUniqueId()
bool timeSpecified() const
Definition: CVEX_Context.h:138
GLuint start
Definition: glcorearb.h:475
const CVEX_ValueT< PREC > * findInput(const UT_StringRef &name) const
Find an input by name.
Definition: CVEX_Context.h:323
UT_OpCaller * getOpCaller() const
Access to the OP_Caller.
Definition: CVEX_Context.h:80
void setWorldNodeId(int id)
Definition: CVEX_Context.h:67
const exint * getProcId() const
Definition: CVEX_Context.h:113
int64 exint
Definition: SYS_Types.h:125
void setGeoInputs(const VEX_GeoInputs *geo)
Definition: CVEX_Context.h:101
void setTimeDependent(bool v)
Definition: CVEX_Context.h:145
const CVEX_ValueT< PREC > * findOutput(const UT_StringRef &name, CVEX_Type type) const
Find an output by name/type.
Definition: CVEX_Context.h:339
GLuint const GLchar * name
Definition: glcorearb.h:786
CVEX_ValueT< PREC > * findInput(const UT_StringRef &name)
Definition: CVEX_Context.h:325
VEX_GeoCommandQueue< PREC > * getGeoCommandQueue() const
Definition: CVEX_Context.h:120
const CVEX_ValueT< PREC > * findOutput(const UT_StringRef &name) const
Find and output by name.
Definition: CVEX_Context.h:345
GLenum GLsizei GLsizei GLint * values
Definition: glcorearb.h:1602
std::unique_ptr< T, Deleter > UT_UniquePtr
A smart pointer for unique ownership of dynamically allocated objects.
Definition: UT_UniquePtr.h:39
List of input or output values for a CVEX_Context.
A class representing a VEX value.
Definition: CVEX_Value.h:59
int cwdId() const
Definition: CVEX_Context.h:140
void setCWDNodeId(int id)
Definition: CVEX_Context.h:60
bool isTimeDependent() const
Definition: CVEX_Context.h:84
const CVEX_ValueListT< PREC > & getInputList() const
Definition: CVEX_Context.h:314
std::shared_ptr< T > UT_SharedPtr
Wrapper around std::shared_ptr.
Definition: UT_SharedPtr.h:36
void setTimeSampleEncountered(bool v)
Set flag indicating whether there are any time samples involved.
Definition: CVEX_Context.h:87
const CVEX_ValueT< PREC > * findInput(const UT_StringRef &name, CVEX_Type type) const
Find an input by name/type.
Definition: CVEX_Context.h:317
const GLdouble * v
Definition: glcorearb.h:837
void setTime(fpreal time)
Definition: CVEX_Context.h:50
CVEX_ProbeResult
Definition: CVEX_Context.h:185
void setProcId(exint *procid)
Definition: CVEX_Context.h:109
GLsizei const GLchar *const * strings
Definition: glcorearb.h:1933
CVEX_Type
The CVEX_Type enum defines the VEX types available to CVEX.
Definition: CVEX_Value.h:29
CVEX_ValueT< PREC > * findOutput(const UT_StringRef &name)
Definition: CVEX_Context.h:347
int worldId() const
Definition: CVEX_Context.h:141
CVEX_ValueListT< PREC > & getOutputList()
Definition: CVEX_Context.h:336
CVEX_ValueT< PREC > * findOutput(const UT_StringRef &name, CVEX_Type type)
Definition: CVEX_Context.h:341
A class holding a VEX function.
Definition: CVEX_Function.h:30
void setGeoCommandQueue(VEX_GeoCommandQueue< PREC > *geocmd)
Sets the command queue for this context.
Definition: CVEX_Context.h:116
const CVEX_ValueListT< PREC > & getOutputList() const
Definition: CVEX_Context.h:335
CVEX_Transform & getTransform()
Definition: CVEX_Context.h:134
fpreal64 fpreal
Definition: SYS_Types.h:277
#define CVEX_API
Definition: CVEX_API.h:12
CVEX_ValueT< PREC > * findInput(const UT_StringRef &name, CVEX_Type type)
Definition: CVEX_Context.h:319
CVEX_EXTERN_TEMPLATE(CVEX_RunDataT< VEX_32 >)
Per-run data for CVEX execution.
Definition: CVEX_Context.h:38
typename VEX_PrecisionResolver< P >::int_type VEXint
Definition: VEX_PodTypes.h:68
Definition: core.h:1131
bool timeDependent() const
Definition: CVEX_Context.h:139
void setOpCaller(UT_OpCaller *caller)
Definition: CVEX_Context.h:74
void clear()
Resets list to an empty list.
Definition: UT_Array.h:679
bool isTimeSampleEncountered() const
Definition: CVEX_Context.h:94
type
Definition: core.h:1059
Call VEX from C++.
Definition: CVEX_Context.h:203
Definition: format.h:895
CVEX_API exint CVEXgetGlobalContextClearCount()