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