BRL-CAD
oslexec_pvt.h
Go to the documentation of this file.
1 /*
2 Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al.
3 All Rights Reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 * Redistributions of source code must retain the above copyright
9  notice, this list of conditions and the following disclaimer.
10 * Redistributions in binary form must reproduce the above copyright
11  notice, this list of conditions and the following disclaimer in the
12  documentation and/or other materials provided with the distribution.
13 * Neither the name of Sony Pictures Imageworks nor the names of its
14  contributors may be used to endorse or promote products derived from
15  this software without specific prior written permission.
16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #ifndef LIBOPTICAL_OSLEXEC_PVT_H
30 #define LIBOPTICAL_OSLEXEC_PVT_H
31 
32 #include "common.h"
33 
34 #include <string>
35 #include <vector>
36 #include <stack>
37 #include <map>
38 #include <list>
39 #include <set>
40 
41 #include <boost/regex_fwd.hpp>
42 
43 #include "OpenImageIO/hash.h"
44 #include "OpenImageIO/ustring.h"
45 #include "OpenImageIO/thread.h"
46 #include "OpenImageIO/paramlist.h"
47 
48 #include "oslexec.h"
49 #include "oslclosure.h"
50 #include "osl_pvt.h"
51 #include "constantpool.h"
52 
53 
54 using namespace OSL;
55 using namespace OSL::pvt;
56 
57 namespace llvm {
58  class ExecutionEngine;
59  class Function;
60  class FunctionPassManager;
61  class LLVMContext;
62  class Linker;
63  class Module;
64  class PassManager;
65  class JITMemoryManager;
66 }
67 
68 #ifdef OSL_NAMESPACE
69 namespace OSL_NAMESPACE {
70 #endif
71 
72 namespace OSL {
73 namespace pvt {
74 
75 #ifdef OIIO_NAMESPACE
76 using OIIO::atomic_int;
77 using OIIO::atomic_ll;
78 using OIIO::RefCnt;
79 using OIIO::ParamValueList;
80 using OIIO::spin_mutex;
81 using OIIO::thread_specific_ptr;
82 using OIIO::ustringHash;
83 namespace Strutil = OIIO::Strutil;
84 #endif
85 
86 // forward definitions
87 class ShadingSystemImpl;
88 class ShadingContext;
90 typedef shared_ptr<ShaderInstance> ShaderInstanceRef;
91 class Dictionary;
92 
93 
94 /// Signature of the function that LLVM generates to run the shader
95 /// group.
96 typedef void (*RunLLVMGroupFunc)(void* /* shader globals */, void*);
97 
98 
99 // Prefix for OSL shade up declarations, so LLVM can find them
100 #ifdef _MSC_VER
101 #define OSL_SHADEOP extern "C" __declspec(dllexport)
102 #else
103 #define OSL_SHADEOP extern "C"
104 #endif
105 
106 
107 /// Like an int (of type T), but also internally keeps track of the
108 /// maximum value is has held, and the total "requested" deltas.
109 /// You really shouldn't use an unsigned type for T, for two reasons:
110 /// (1) Our implementation of '-=' will fail; and (2) you actually
111 /// want to allow the counter to go negative, to detect if you have
112 /// made a mistake in your bookkeeping by forgetting an allocation.
113 template<typename T>
115 {
116 public:
117  typedef T value_t;
118  PeakCounter () : m_current(0), m_requested(0), m_peak(0) { }
119  /// Reset all counts to zero.
120  ///
121  void clear () {
122  m_current = 0; m_requested = 0; m_peak = 0;
123  }
124  /// Return the current value.
125  ///
126  value_t operator() () const { return m_current; }
127 
128  /// Return the current value.
129  ///
130  value_t current (void) const { return m_current; }
131  /// Return the sum of all requests.
132  ///
133  value_t requested (void) const { return m_requested; }
134  /// Return the peak value we saw.
135  ///
136  value_t peak (void) const { return m_peak; }
137 
138  /// Reassign the current value, adjust peak and requested as necessary.
139  ///
140  const value_t operator= (value_t newval) {
141  value_t cur = m_current;
142  if (newval > cur)
143  m_requested += (cur-newval);
144  m_current = newval;
145  if (newval > m_peak)
146  m_peak = newval;
147  return m_current;
148  }
149  /// Add to current value, adjust peak and requested as necessary.
150  ///
151  const value_t operator+= (value_t sz) {
152  m_current += sz;
153  if (sz > 0) {
154  m_requested += sz;
155  if (m_current > m_peak)
156  m_peak = m_current;
157  }
158  return m_current;
159  }
160  /// Subtract from current value
161  ///
162  const value_t operator-= (value_t sz) {
163  *this += (-sz);
164  return m_current;
165  }
166 
167  const value_t operator++ () { *this += 1; return m_current; }
168  const value_t operator++ (int) { *this += 1; return m_current-1; }
169  const value_t operator-- () { *this -= 1; return m_current; }
170  const value_t operator-- (int) { *this -= 1; return m_current+1; }
171 
172  friend std::ostream & operator<< (std::ostream &out, const PeakCounter &p)
173  {
174  out << p.requested() << " requested, " << p.peak() << " peak, "
175  << p.current() << " current";
176  return out;
177  }
178 
179  std::string memstat () const {
180  return Strutil::memformat(requested()) + " requested, "
181  + Strutil::memformat(peak()) + " peak, "
182  + Strutil::memformat(current()) + " current";
183  }
184 
185 private:
186  value_t m_current, m_requested, m_peak;
187 };
188 
189 
190 /// Template to count a vector's allocated size, in bytes.
191 ///
192 template<class T>
193 inline off_t vectorbytes (const std::vector<T> &v)
194 {
195  return v.capacity() * sizeof(T);
196 }
197 
198 
199 /// Template to fully deallocate a stl container using the swap trick.
200 ///
201 template<class T>
202 inline void stlfree (T &v)
203 {
204  T tmp;
205  std::swap (tmp, v);
206  // Now v is no allocated space, and tmp has v's old allocated space.
207  // When tmp leaves scope as we return, that space will be freed.
208 }
209 
210 
211 /// ShaderMaster is the full internal representation of a complete
212 /// shader that would be a .oso file on disk: symbols, instructions,
213 /// arguments, you name it. A master copy is shared by all the
214 /// individual instances of the shader.
215 class ShaderMaster : public RefCnt {
216 public:
217  typedef intrusive_ptr<ShaderMaster> ref;
218  ShaderMaster (ShadingSystemImpl &shadingsys) : m_shadingsys(shadingsys) { }
219  ~ShaderMaster ();
220 
221  std::string print (); // Debugging
222 
223  /// Return a pointer to the shading system for this master.
224  ///
225  ShadingSystemImpl & shadingsys () const { return m_shadingsys; }
226 
227  /// Run through the symbols and set up various things we can know
228  /// with just the master: the size (including padding), and their
229  /// data pointers if they are constants or params (to the defaults).
230  /// As a side effect, also set this->m_firstparam/m_lastparam.
231  void resolve_syms ();
232 
233  /// Find the named symbol, return its index in the symbol array, or
234  /// -1 if not found.
235  int findsymbol (ustring name) const;
236 
237  /// Return a pointer to the symbol (specified by integer index),
238  /// or NULL (if index was -1, as returned by 'findsymbol').
239  Symbol *symbol (int index) { return index >= 0 ? &m_symbols[index] : NULL; }
240 
241  /// Return the name of the shader.
242  ///
243  const std::string &shadername () const { return m_shadername; }
244 
245 private:
246  ShadingSystemImpl &m_shadingsys; ///< Back-ptr to the shading system
247  ShaderType m_shadertype; ///< Type of shader
248  std::string m_shadername; ///< Shader name
249  std::string m_osofilename; ///< Full path of oso file
250  OpcodeVec m_ops; ///< Actual code instructions
251  std::vector<int> m_args; ///< Arguments for all the ops
252  // Need the code offsets for each code block
253  SymbolVec m_symbols; ///< Symbols used by the shader
254  std::vector<int> m_idefaults; ///< int default param values
255  std::vector<float> m_fdefaults; ///< float default param values
256  std::vector<ustring> m_sdefaults; ///< string default param values
257  std::vector<int> m_iconsts; ///< int constant values
258  std::vector<float> m_fconsts; ///< float constant values
259  std::vector<ustring> m_sconsts; ///< string constant values
260  int m_firstparam, m_lastparam; ///< Subset of symbols that are params
261  int m_maincodebegin, m_maincodeend; ///< Main shader code range
262 
263  friend class OSOReaderToMaster;
264  friend class ShaderInstance;
265 };
266 
267 
268 /// Describe one end of a parameter connection: the parameter number, and
269 /// optionally an array index and/or channel number within that parameter.
271  int param; ///< Parameter number (in the symbol table)
272  int arrayindex; ///< Array index (-1 for not an index)
273  int channel; ///< Channel number (-1 for no channel selection)
274  int offset; ///< Offset into the data of the element/channel
275  TypeSpec type; ///< Type of data being connected
276 
277  ConnectedParam () : param(-1), arrayindex(-1), channel(-1), offset(0) { }
278 
279  bool valid () const { return (param >= 0); }
280 };
281 
282 
283 /// Describe a parameter connection to an earlier layer.
284 ///
285 struct Connection {
286  int srclayer; ///< Layer (within our group) of the source
287  ConnectedParam src; ///< Which source parameter (or part thereof)
288  ConnectedParam dst; ///< Which destination parameter (or part thereof)
289 
290  Connection (int srclay, const ConnectedParam &srccon,
291  const ConnectedParam &dstcon)
292  : srclayer (srclay), src (srccon), dst (dstcon)
293  { }
294 };
295 
296 
297 typedef std::vector<Connection> ConnectionVec;
298 
299 
300 /// ShaderInstance is a particular instance of a shader, with its own
301 /// set of parameter values, coordinate transform, and connections to
302 /// other instances within the same shader group.
304 public:
305  typedef ShaderInstanceRef ref;
306  ShaderInstance (ShaderMaster::ref master, const char *layername="");
307  ~ShaderInstance ();
308 
309  /// Return the layer name of this instance
310  ///
311  ustring layername () const { return m_layername; }
312 
313  /// Return the name of the shader used by this instance.
314  ///
315  const std::string &shadername () const { return m_master->shadername(); }
316 
317  /// Return a pointer to the master for this instance.
318  ///
319  ShaderMaster *master () const { return m_master.get(); }
320 
321  /// Return a reference to the shading system for this instance.
322  ///
323  ShadingSystemImpl & shadingsys () const { return m_master->shadingsys(); }
324 
325  /// Apply pending parameters
326  ///
327  void parameters (const ParamValueList &params);
328 
329  /// Find the named symbol, return its index in the symbol array, or
330  /// -1 if not found.
331  int findsymbol (ustring name) const;
332 
333  /// Find the named parameter, return its index in the symbol array, or
334  /// -1 if not found.
335  int findparam (ustring name) const;
336 
337  /// Return a pointer to the symbol (specified by integer index),
338  /// or NULL (if index was -1, as returned by 'findsymbol').
339  Symbol *symbol (int index) { return index >= 0 ? &m_instsymbols[index] : NULL; }
340  const Symbol *symbol (int index) const { return index >= 0 ? &m_instsymbols[index] : NULL; }
341 
342  /// Estimate how much to round the required heap size up if npoints
343  /// is odd, to account for getting the desired alignment for each
344  /// symbol.
345  size_t heapround ();
346 
347  /// Add a connection
348  ///
349  void add_connection (int srclayer, const ConnectedParam &srccon,
350  const ConnectedParam &dstcon);
351 
352  /// How many connections to earlier layers do we have?
353  ///
354  int nconnections () const { return (int) m_connections.size (); }
355 
356  /// Return a reference to the i-th connection to an earlier layer.
357  ///
358  const Connection & connection (int i) const { return m_connections[i]; }
359 
360  /// Reference to the connection list.
361  ///
362  ConnectionVec & connections () { return m_connections; }
363  const ConnectionVec & connections () const { return m_connections; }
364 
365  /// Return the unique ID of this instance.
366  ///
367  int id () const { return m_id; }
368 
369  /// Does this instance potentially write to any global vars?
370  ///
371  bool writes_globals () const { return m_writes_globals; }
372 
373  /// Should this instance only be run lazily (i.e., not
374  /// unconditionally)?
375  bool run_lazily () const { return m_run_lazily; }
376  void run_lazily (bool lazy) { m_run_lazily = lazy; }
377 
378  /// Does this instance have any outgoing connections?
379  ///
380  bool outgoing_connections () const { return m_outgoing_connections; }
381  /// Set whether this instance has outgoing connections.
382  ///
383  void outgoing_connections (bool out) { m_outgoing_connections = out; }
384 
385  int maincodebegin () const { return m_maincodebegin; }
386  int maincodeend () const { return m_maincodeend; }
387 
388  int firstparam () const { return m_firstparam; }
389  int lastparam () const { return m_lastparam; }
390 
391  /// Return a begin/end Symbol* pair for the set of param symbols
392  /// that is suitable to pass as a range for BOOST_FOREACH.
393  friend std::pair<Symbol *,Symbol *> param_range (ShaderInstance *i) {
394  return std::pair<Symbol*,Symbol*> (i->symbol(i->firstparam()),
395  i->symbol(i->lastparam()));
396  }
397 
398  friend std::pair<const Symbol *,const Symbol *> param_range (const ShaderInstance *i) {
399  return std::pair<const Symbol*,const Symbol*> (i->symbol(i->firstparam()),
400  i->symbol(i->lastparam()));
401  }
402 
403  int Psym () const { return m_Psym; }
404  int Nsym () const { return m_Nsym; }
405 
406 
407  const std::vector<int> & args () const { return m_instargs; }
408  std::vector<int> & args () { return m_instargs; }
409  int arg (int argnum) { return args()[argnum]; }
410  Symbol *argsymbol (int argnum) { return symbol(arg(argnum)); }
411  const OpcodeVec & ops () const { return m_instops; }
412  OpcodeVec & ops () { return m_instops; }
413 
414  std::string print (); // Debugging
415 
416  SymbolVec &symbols () { return m_instsymbols; }
417  const SymbolVec &symbols () const { return m_instsymbols; }
418 
419  /// Make sure there's room for more symbols.
420  ///
421  void make_symbol_room (size_t moresyms=1);
422 
423  /// Does it appear that the layer is completely unused?
424  ///
425  bool unused () const { return run_lazily() && ! outgoing_connections(); }
426 
427  /// Make our own version of the code and args from the master.
428  ///
429  void copy_code_from_master ();
430 
431 private:
432  ShaderMaster::ref m_master; ///< Reference to the master
433  SymbolVec m_instsymbols; ///< Symbols used by the instance
434  OpcodeVec m_instops; ///< Actual code instructions
435  std::vector<int> m_instargs; ///< Arguments for all the ops
436  ustring m_layername; ///< Name of this layer
437  std::vector<int> m_iparams; ///< int param values
438  std::vector<float> m_fparams; ///< float param values
439  std::vector<ustring> m_sparams; ///< string param values
440  int m_id; ///< Unique ID for the instance
441  bool m_writes_globals; ///< Do I have side effects?
442  bool m_run_lazily; ///< OK to run this layer lazily?
443  bool m_outgoing_connections; ///< Any outgoing connections?
444  std::vector<Connection> m_connections; ///< Connected input params
445  int m_firstparam, m_lastparam; ///< Subset of symbols that are params
446  int m_maincodebegin, m_maincodeend; ///< Main shader code range
447  int m_Psym, m_Nsym; ///< Quick lookups of common syms
448 
449  friend class ShadingSystemImpl;
450  friend class RuntimeOptimizer;
451 };
452 
453 
454 /// Macro to loop over just the params & output params of an instance,
455 /// with each iteration providing a Symbol& to symbolref. Use like this:
456 /// FOREACH_PARAM (Symbol &s, inst) { ... stuff with s... }
457 ///
458 #define FOREACH_PARAM(symboldecl,inst) \
459  BOOST_FOREACH (symboldecl, param_range(inst))
460 
461 
462 /// A ShaderGroup consists of one or more layers (each of which is a
463 /// ShaderInstance), and the connections among them.
464 class ShaderGroup {
465 public:
466  ShaderGroup ();
467  ShaderGroup (const ShaderGroup &g);
468  ~ShaderGroup ();
469 
470  /// Clear the layers
471  ///
472  void clear () { m_layers.clear (); m_optimized = 0; m_executions = 0; }
473 
474  /// Append a new shader instance on to the end of this group
475  ///
476  void append (ShaderInstanceRef newlayer) {
477  ASSERT (! m_optimized && "should not append to optimized group");
478  m_layers.push_back (newlayer);
479  }
480 
481  /// How many layers are in this group?
482  ///
483  int nlayers () const { return (int) m_layers.size(); }
484 
485  /// Array indexing returns the i-th layer of the group
486  ///
487  ShaderInstance * operator[] (int i) const { return m_layers[i].get(); }
488 
489  int optimized () const { return m_optimized; }
490  void optimized (int opt) { m_optimized = opt; }
491 
492  size_t llvm_groupdata_size () const { return m_llvm_groupdata_size; }
493  void llvm_groupdata_size (size_t size) { m_llvm_groupdata_size = size; }
494 
496  return m_llvm_compiled_version;
497  }
499  m_llvm_compiled_version = func;
500  }
501 
502  /// Is this shader group equivalent to ret void?
503  bool does_nothing() const {
504  return m_does_nothing;
505  }
506  void does_nothing(bool new_val) {
507  m_does_nothing = new_val;
508  }
509 
510  long long int executions () const { return m_executions; }
511 
512  void start_running () {
513 #ifdef DEBUG
514  m_executions++;
515 #endif
516  }
517 
518 private:
519  std::vector<ShaderInstanceRef> m_layers;
520  RunLLVMGroupFunc m_llvm_compiled_version;
521  size_t m_llvm_groupdata_size;
522  volatile int m_optimized; ///< Is it already optimized?
523  bool m_does_nothing; ///< Is the shading group just func() { return; }
524  atomic_ll m_executions; ///< Number of times the group executed
525  mutex m_mutex; ///< Thread-safe optimization
526  friend class ShadingSystemImpl;
527 };
528 
529 
531 public:
532 
533  struct ClosureEntry {
534  // normally a closure is fully identified by its
535  // name, but we might want to have an internal id
536  // for fast dispatching
537  int id;
538  // The name again
539  ustring name;
540  // Number of formal arguments
541  int nformal;
542  // Number of keyword arguments
543  int nkeyword;
544  // The parameters
545  std::vector<ClosureParam> params;
546  // the needed size for the structure
548  // Creation callbacks
549  PrepareClosureFunc prepare;
550  SetupClosureFunc setup;
551  CompareClosureFunc compare;
552  };
553 
554  void register_closure (const char *name, int id, const ClosureParam *params, int size,
555  PrepareClosureFunc prepare, SetupClosureFunc setup, CompareClosureFunc compare);
556 
557  const ClosureEntry *get_entry (ustring name) const;
558  const ClosureEntry *get_entry (int id) const {
559  DASSERT((size_t)id < m_closure_table.size());
560  return &m_closure_table[id];
561  }
562 
563  bool empty () const { return m_closure_table.empty(); }
564 
565 private:
566 
567 
568  // A mapping from name to ID for the compiler
569  std::map<ustring, int> m_closure_name_to_id;
570  // And the internal global table, indexed
571  // by the internal ID for fast dispatching
572  std::vector<ClosureEntry> m_closure_table;
573 };
574 
575 
576 class OSLEXECPUBLIC ShadingSystemImpl : public ShadingSystem
577 {
578 public:
579  ShadingSystemImpl (RendererServices *renderer=NULL,
580  TextureSystem *texturesystem=NULL,
581  ErrorHandler *err=NULL);
582  virtual ~ShadingSystemImpl ();
583 
584  virtual bool attribute (const std::string &name, TypeDesc type, const void *val);
585  virtual bool getattribute (const std::string &name, TypeDesc type, void *val);
586 
587  virtual bool Parameter (const char *name, TypeDesc t, const void *val);
588  virtual bool Shader (const char *shaderusage,
589  const char *shadername=NULL,
590  const char *layername=NULL);
591  virtual bool ShaderGroupBegin (void);
592  virtual bool ShaderGroupEnd (void);
593  virtual bool ConnectShaders (const char *srclayer, const char *srcparam,
594  const char *dstlayer, const char *dstparam);
595  virtual ShadingAttribStateRef state () const;
596  virtual void clear_state ();
597 
598 // virtual void RunShaders (ShadingAttribStateRef &attribstate,
599 // ShaderUse use);
600 
601  /// Internal error reporting routine, with printf-like arguments.
602  ///
603  void error (const char *message, ...);
604  /// Internal warning reporting routine, with printf-like arguments.
605  ///
606  void warning (const char *message, ...);
607  /// Internal info printing routine, with printf-like arguments.
608  ///
609  void info (const char *message, ...);
610  /// Internal message printing routine, with printf-like arguments.
611  ///
612  void message (const char *message, ...);
613 
614  /// Error reporting routines that take a pre-formatted string only.
615  ///
616  void error (const std::string &message);
617  void warning (const std::string &message);
618  void info (const std::string &message);
619  void message (const std::string &message);
620 
621  virtual std::string getstats (int level=1) const;
622 
623  ErrorHandler &errhandler () const { return *m_err; }
624 
625  ShaderMaster::ref loadshader (const char *name);
626 
627  void* create_thread_info();
628 
629  void destroy_thread_info(void* thread_info);
630 
631  /// Get a ShadingContext that we can use.
632  ///
633  ShadingContext *get_context (void* thread_info = NULL);
634 
635  /// Return a ShadingContext to the pool.
636  ///
637  void release_context (ShadingContext *sc, void* thread_info = NULL);
638 
639  void operator delete (void *todel) { ::delete ((char *)todel); }
640 
641  /// Return the precomputed heap offset of the named global, or -1 if
642  /// it's not precomputed.
643  int global_heap_offset (ustring name);
644 
645  /// Is the shading system in debug mode?
646  ///
647  bool debug () const { return m_debug; }
648 
649  /// Return a pointer to the renderer services object.
650  ///
651  RendererServices *renderer () const { return m_renderer; }
652 
653  /// Return a pointer to the texture system.
654  ///
655  TextureSystem *texturesys () const { return m_texturesys; }
656 
657  bool allow_rebind () const { return m_rebind; }
658 
659  bool debug_nan () const { return m_debugnan; }
660  bool lockgeom_default () const { return m_lockgeom_default; }
661  int optimize () const { return m_optimize; }
662  int llvm_debug () const { return m_llvm_debug; }
663 
664  ustring commonspace_synonym () const { return m_commonspace_synonym; }
665 
666  /// The group is set and won't be changed again; take advantage of
667  /// this by optimizing the code knowing all our instance parameters
668  /// (at least the ones that can't be overridden by the geometry).
669  void optimize_group (ShadingAttribState &attribstate, ShaderGroup &group);
670 
671  int *alloc_int_constants (size_t n) { return m_int_pool.alloc (n); }
672  float *alloc_float_constants (size_t n) { return m_float_pool.alloc (n); }
673  ustring *alloc_string_constants (size_t n) { return m_string_pool.alloc (n); }
674 
675  llvm::LLVMContext *llvm_context () { return m_llvm_context; }
676  llvm::ExecutionEngine* ExecutionEngine () { return m_llvm_exec; }
677 
678  virtual void register_closure(const char *name, int id, const ClosureParam *params, int size,
679  PrepareClosureFunc prepare, SetupClosureFunc setup, CompareClosureFunc compare);
680  const ClosureRegistry::ClosureEntry *find_closure(ustring name) const {
681  return m_closure_registry.get_entry(name);
682  }
684  return m_closure_registry.get_entry(id);
685  }
686 
687  /// Convert a color in the named space to RGB.
688  ///
689  Color3 to_rgb (ustring fromspace, float a, float b, float c);
690 
691  /// For the proposed raytype name, return the bit pattern that
692  /// describes it, or 0 for an unrecognized name.
693  int raytype_bit (ustring name);
694 
695 private:
696  void printstats () const;
697  void init_global_heap_offsets ();
698 
699  /// Find the index of the named layer in the current shader group.
700  /// If found, return the index >= 0 and put a pointer to the instance
701  /// in inst; if not found, return -1 and set inst to NULL.
702  /// (This is a helper for ConnectShaders.)
703  int find_named_layer_in_group (ustring layername, ShaderInstance * &inst);
704 
705  /// Turn a connectionname (such as "Kd" or "Cout[1]", etc.) into a
706  /// ConnectedParam descriptor. This routine is strictly a helper for
707  /// ConnectShaders, and will issue error messages on its behalf.
708  /// The return value will not be valid() if there is an error.
709  ConnectedParam decode_connected_param (const char *connectionname,
710  const char *layername, ShaderInstance *inst);
711 
712  struct PerThreadInfo {
713  std::stack<ShadingContext *> context_pool;
714 
715  ShadingContext *pop_context (); ///< Get the pool top and then pop
716  ~PerThreadInfo ();
717  };
718 
719  /// Get the per-thread info, create it if necessary.
720  ///
721  PerThreadInfo *get_perthread_info () const {
722  PerThreadInfo *p = m_perthread_info.get ();
723  if (! p) {
724  p = new PerThreadInfo;
725  m_perthread_info.reset (p);
726  }
727  return p;
728  }
729 
730  /// Set up LLVM -- make sure we have a Context, Module, ExecutionEngine,
731  /// retained JITMemoryManager, etc.
732  void SetupLLVM ();
733 
734  RendererServices *m_renderer; ///< Renderer services
735  TextureSystem *m_texturesys; ///< Texture system
736 
737  ErrorHandler *m_err; ///< Error handler
738  std::list<std::string> m_errseen, m_warnseen;
739  static const int m_errseenmax = 32;
740  mutable mutex m_errmutex;
741 
742  typedef std::map<ustring,ShaderMaster::ref> ShaderNameMap;
743  ShaderNameMap m_shader_masters; ///< name -> shader masters map
744 
745  ConstantPool<int> m_int_pool;
746  ConstantPool<Float> m_float_pool;
747  ConstantPool<ustring> m_string_pool;
748 
749  // Options
750  int m_statslevel; ///< Statistics level
751  bool m_debug; ///< Debugging output
752  bool m_lazylayers; ///< Evaluate layers on demand?
753  bool m_lazyglobals; ///< Run lazily even if globals write?
754  bool m_clearmemory; ///< Zero mem before running shader?
755  bool m_rebind; ///< Allow rebinding?
756  bool m_debugnan; ///< Root out NaN's?
757  bool m_lockgeom_default; ///< Default value of lockgeom
758  int m_optimize; ///< Runtime optimization level
759  int m_llvm_debug; ///< More LLVM debugging output
760  std::string m_searchpath; ///< Shader search path
761  std::vector<std::string> m_searchpath_dirs; ///< All searchpath dirs
762  ustring m_commonspace_synonym; ///< Synonym for "common" space
763  std::vector<ustring> m_raytypes; ///< Names of ray types
764 
765  bool m_in_group; ///< Are we specifying a group?
766  ShaderUse m_group_use; ///< Use of group
767  ParamValueList m_pending_params; ///< Pending Parameter() values
768  ShadingAttribStateRef m_curattrib; ///< Current shading attribute state
769  std::map<ustring,int> m_global_heap_offsets; ///< Heap offsets of globals
770  size_t m_global_heap_total; ///< Heap size for globals
771  mutable mutex m_mutex; ///< Thread safety
772  mutable thread_specific_ptr<PerThreadInfo> m_perthread_info;
773 
774  // Stats
775  atomic_int m_stat_shaders_loaded; ///< Stat: shaders loaded
776  atomic_int m_stat_shaders_requested; ///< Stat: shaders requested
777  PeakCounter<int> m_stat_instances; ///< Stat: instances
778  PeakCounter<int> m_stat_contexts; ///< Stat: shading contexts
779  int m_stat_groups; ///< Stat: shading groups
780  int m_stat_groupinstances; ///< Stat: total inst in all groups
781  atomic_int m_stat_regexes; ///< Stat: how many regex's compiled
782  atomic_ll m_layers_executed_uncond; ///< Stat: Unconditional execs
783  atomic_ll m_layers_executed_lazy; ///< Stat: On-demand execs
784  atomic_ll m_layers_executed_never; ///< Stat: Layers never executed
785  atomic_ll m_stat_binds; ///< Stat: Number of binds;
786  atomic_ll m_stat_rebinds; ///< Stat: Number of rebinds;
787  atomic_ll m_stat_paramstobind; ///< Stat: All params in bound shaders
788  atomic_ll m_stat_paramsbound; ///< Stat: Number of params bound
789  atomic_ll m_stat_instructions_run; ///< Stat: total instructions run
790  atomic_int m_stat_total_syms; ///< Stat: total syms in all insts
791  atomic_int m_stat_syms_with_derivs; ///< Stat: syms with derivatives
792  double m_stat_optimization_time; ///< Stat: time spent optimizing
793  double m_stat_opt_locking_time; ///< locking time
794  double m_stat_specialization_time; ///< runtime specialization time
795  double m_stat_total_llvm_time; ///< total time spent on LLVM
796  double m_stat_llvm_setup_time; ///< llvm setup time
797  double m_stat_llvm_irgen_time; ///< llvm IR generation time
798  double m_stat_llvm_opt_time; ///< llvm IR optimization time
799  double m_stat_llvm_jit_time; ///< llvm JIT time
800 
801  PeakCounter<off_t> m_stat_memory; ///< Stat: all shading system memory
802 
803  PeakCounter<off_t> m_stat_mem_master; ///< Stat: master-related mem
804  PeakCounter<off_t> m_stat_mem_master_ops;
805  PeakCounter<off_t> m_stat_mem_master_args;
806  PeakCounter<off_t> m_stat_mem_master_syms;
807  PeakCounter<off_t> m_stat_mem_master_defaults;
808  PeakCounter<off_t> m_stat_mem_master_consts;
809  PeakCounter<off_t> m_stat_mem_inst; ///< Stat: instance-related mem
810  PeakCounter<off_t> m_stat_mem_inst_ops;
811  PeakCounter<off_t> m_stat_mem_inst_args;
812  PeakCounter<off_t> m_stat_mem_inst_syms;
813  PeakCounter<off_t> m_stat_mem_inst_paramvals;
814  PeakCounter<off_t> m_stat_mem_inst_connections;
815 
816  spin_mutex m_stat_mutex; ///< Mutex for non-atomic stats
817  ClosureRegistry m_closure_registry;
818 
819  // LLVM stuff
820  llvm::LLVMContext *m_llvm_context;
821  llvm::Module *m_llvm_module;
822  llvm::ExecutionEngine *m_llvm_exec;
823  llvm::JITMemoryManager *m_llvm_jitmm;
824 
825  friend class ShadingContext;
826  friend class ShaderMaster;
827  friend class ShaderInstance;
828  friend class RuntimeOptimizer;
829 };
830 
831 
832 template<int BlockSize>
833 class SimplePool {
834 public:
836  m_blocks.push_back(new char[BlockSize]);
837  m_block_offset = BlockSize;
838  m_current_block = 0;
839  }
840 
842  for (size_t i =0; i < m_blocks.size(); ++i)
843  delete [] m_blocks[i];
844  }
845 
846  char * alloc(size_t size) {
847  ASSERT(size < BlockSize);
848  if (size <= m_block_offset) {
849  m_block_offset -= size;
850  } else {
851  m_current_block++;
852  m_block_offset = BlockSize - size;
853  if (m_blocks.size() == m_current_block)
854  m_blocks.push_back(new char[BlockSize]);
855  }
856  return m_blocks[m_current_block] + m_block_offset;
857  }
858 
859  void clear () { m_current_block = 0; m_block_offset = BlockSize; }
860 
861 private:
862  std::vector<char *> m_blocks;
863  size_t m_current_block;
864  size_t m_block_offset;
865 };
866 
867 
868 /// The full context for executing a shader group.
869 ///
870 class OSLEXECPUBLIC ShadingContext {
871 public:
872  ShadingContext (ShadingSystemImpl &shadingsys);
873  ~ShadingContext ();
874 
875  /// Return a reference to the shading system for this context.
876  ///
877  ShadingSystemImpl & shadingsys () const { return m_shadingsys; }
878 
879  /// Get a pointer to the RendererServices for this execution.
880  ///
881  RendererServices *renderer () const { return m_renderer; }
882 
883  /// Execute the shaders for the given use (for example,
884  /// ShadUseSurface). If runflags are not supplied, they will be
885  /// auto-generated with all points turned on.
886  void execute (ShaderUse use, ShadingAttribState &sas,
887  ShaderGlobals &ssg);
888 
889  /// Return the current shader use being executed.
890  ///
891  ShaderUse use () const { return (ShaderUse) m_curuse; }
892 
893  ClosureComponent * closure_component_allot(int id, size_t prim_size, int nattrs) {
894  size_t needed = sizeof(ClosureComponent) + (prim_size >= 4 ? prim_size - 4 : 0)
895  + sizeof(ClosureComponent::Attr) * nattrs;
896  ClosureComponent *comp = (ClosureComponent *) m_closure_pool.alloc(needed);
897  comp->type = ClosureColor::COMPONENT;
898  comp->id = id;
899  comp->size = prim_size;
900  comp->nattrs = nattrs;
901  return comp;
902  }
903 
904  ClosureMul *closure_mul_allot (const Color3 &w, const ClosureColor *c) {
905  ClosureMul *mul = (ClosureMul *) m_closure_pool.alloc(sizeof(ClosureMul));
906  mul->type = ClosureColor::MUL;
907  mul->weight = w;
908  mul->closure = c;
909  return mul;
910  }
911 
912  ClosureMul *closure_mul_allot (float w, const ClosureColor *c) {
913  ClosureMul *mul = (ClosureMul *) m_closure_pool.alloc(sizeof(ClosureMul));
914  mul->type = ClosureColor::MUL;
915  mul->weight.setValue (w,w,w);
916  mul->closure = c;
917  return mul;
918  }
919 
920  ClosureAdd *closure_add_allot (const ClosureColor *a, const ClosureColor *b) {
921  ClosureAdd *add = (ClosureAdd *) m_closure_pool.alloc(sizeof(ClosureAdd));
922  add->type = ClosureColor::ADD;
923  add->closureA = a;
924  add->closureB = b;
925  return add;
926  }
927 
928 
929  /// Find the named symbol in the (already-executed!) stack of
930  /// shaders of the given use, with priority given to
931  /// later layers over earlier layers (if they name the same symbol).
932  /// Return NULL if no such symbol is found.
933  Symbol * symbol (ShaderUse use, ustring name);
934 
935  /// Return a pointer to where the symbol's data lives for the given
936  /// grid point.
937  void *symbol_data (Symbol &sym, int gridpoint);
938 
939  /// Return a reference to a compiled regular expression for the
940  /// given string, being careful to cache already-created ones so we
941  /// aren't constantly compiling new ones.
942  const boost::regex & find_regex (ustring r);
943 
944  /// Return a pointer to the shading attribs for this context.
945  ///
946  ShadingAttribState *attribs () { return m_attribs; }
947 
948  /// Return a reference to the ParamValueList containing messages.
949  ///
950  ParamValueList & messages () { return m_messages; }
951 
952  /// Look up a query from a dictionary (typically XML), staring the
953  /// search from the root of the dictionary, and returning ID of the
954  /// first matching node.
955  int dict_find (ustring dictionaryname, ustring query);
956  /// Look up a query from a dictionary (typically XML), staring the
957  /// search from the given nodeID within the dictionary, and
958  /// returning ID of the first matching node.
959  int dict_find (int nodeID, ustring query);
960  /// Return the next match of the same query that gave the nodeID.
961  int dict_next (int nodeID);
962  /// Look up an attribute of the given dictionary node. If
963  /// attribname is "", return the value of the node itself.
964  int dict_value (int nodeID, ustring attribname, TypeDesc type, void *data);
965 
966  /// Various setup of the context done by execute(). Return true if
967  /// the function should be executed, otherwise false.
968  bool prepare_execution (ShaderUse use, ShadingAttribState &sas);
969 private:
970 
971  /// Execute the llvm-compiled shaders for the given use (for example,
972  /// ShadUseSurface). The context must already be bound. If
973  /// runflags are not supplied, they will be auto-generated with all
974  /// points turned on.
975  void execute_llvm (ShaderUse use, Runflag *rf=NULL,
976  int *ind=NULL, int nind=0);
977 
978  void free_dict_resources ();
979 
980  ShadingSystemImpl &m_shadingsys; ///< Backpointer to shadingsys
981  RendererServices *m_renderer; ///< Ptr to renderer services
982  ShadingAttribState *m_attribs; ///< Ptr to shading attrib state
983  std::vector<char> m_heap; ///< Heap memory
984  size_t m_closures_allotted; ///< Closure memory allotted
985  int m_curuse; ///< Current use that we're running
986 #ifdef OIIO_HAVE_BOOST_UNORDERED_MAP
987  typedef boost::unordered_map<ustring, boost::regex*, ustringHash> RegexMap;
988 #else
989  typedef hash_map<ustring, boost::regex*, ustringHash> RegexMap;
990 #endif
991  RegexMap m_regex_map; ///< Compiled regex's
992  ParamValueList m_messages; ///< Message blackboard
993 
994  SimplePool<20 * 1024> m_closure_pool;
995 
996  Dictionary *m_dictionary;
997 };
998 
999 
1000 }; // namespace pvt
1001 
1002 
1004 {
1005 public:
1007 
1009 
1010  /// Return a reference to the shader group for a particular use
1011  ///
1012  ShaderGroup & shadergroup (ShaderUse use) {
1013  return m_shaders[(int)use];
1014  }
1015 
1016  /// Called when the shaders of the attrib state change (invalidate LLVM ?)
1017  void changed_shaders () { }
1018 
1019 private:
1020  OSL::pvt::ShaderGroup m_shaders[OSL::pvt::ShadUseLast];
1021 };
1022 
1023 
1024 namespace Strings {
1025  extern ustring camera, common, object, shader;
1026  extern ustring rgb, RGB, hsv, hsl, YIQ, xyz;
1027  extern ustring null, default_;
1028  extern ustring label;
1029  extern ustring sidedness, front, back, both;
1030  extern ustring P, I, N, Ng, dPdu, dPdv, u, v, time, dtime, dPdtime, Ps;
1031  extern ustring Ci;
1032  extern ustring width, swidth, twidth, rwidth;
1033  extern ustring blur, sblur, tblur, rblur;
1034  extern ustring wrap, swrap, twrap, rwrap;
1035  extern ustring black, clamp, periodic, mirror;
1036  extern ustring firstchannel, fill, alpha;
1037  extern ustring interp, closest, linear, cubic, smartbicubic;
1038 }; // namespace Strings
1039 
1040 
1041 }; // namespace OSL
1042 
1043 #ifdef OSL_NAMESPACE
1044 }; // end namespace OSL_NAMESPACE
1045 using namespace OSL_NAMESPACE;
1046 #endif
1047 
1048 #endif /* LIBOPTICAL_OSLEXEC_PVT_H */
Definition: db_flip.c:35
TypeSpec type
Type of data being connected.
Definition: oslexec_pvt.h:275
Symbol * symbol(int index)
Definition: oslexec_pvt.h:339
ustring swrap
ustring sblur
ustring back
ustring wrap
ConnectedParam src
Which source parameter (or part thereof)
Definition: oslexec_pvt.h:287
intrusive_ptr< ShaderMaster > ref
Definition: oslexec_pvt.h:217
ConnectionVec & connections()
Definition: oslexec_pvt.h:362
ClosureAdd * closure_add_allot(const ClosureColor *a, const ClosureColor *b)
Definition: oslexec_pvt.h:920
const Connection & connection(int i) const
Definition: oslexec_pvt.h:358
int optimized() const
Definition: oslexec_pvt.h:489
int nlayers() const
Definition: oslexec_pvt.h:483
ustring interp
int struct_size
Definition: oslexec_pvt.h:547
int maincodebegin() const
Definition: oslexec_pvt.h:385
llvm::ExecutionEngine * ExecutionEngine()
Definition: oslexec_pvt.h:676
std::vector< int > & args()
Definition: oslexec_pvt.h:408
int offset
Offset into the data of the element/channel.
Definition: oslexec_pvt.h:274
bool does_nothing() const
Is this shader group equivalent to ret void?
Definition: oslexec_pvt.h:503
Definition: oslexec_pvt.h:533
ustring rwidth
const std::string & shadername() const
Definition: oslexec_pvt.h:243
Definition: clone.c:90
#define N
Definition: randmt.c:39
ShaderInstanceRef ref
Definition: oslexec_pvt.h:305
ustring dPdtime
ustring name
Definition: oslexec_pvt.h:539
int id
Definition: oslexec_pvt.h:537
std::vector< Connection > ConnectionVec
Definition: oslexec_pvt.h:297
ustring clamp
ShadingSystemImpl & shadingsys() const
Definition: oslexec_pvt.h:323
std::vector< ClosureParam > params
Definition: oslexec_pvt.h:545
void append(ShaderInstanceRef newlayer)
Definition: oslexec_pvt.h:476
void(* RunLLVMGroupFunc)(void *, void *)
Definition: oslexec_pvt.h:96
ustring dtime
Header file for the BRL-CAD common definitions.
const ClosureRegistry::ClosureEntry * find_closure(ustring name) const
Definition: oslexec_pvt.h:680
int param
Parameter number (in the symbol table)
Definition: oslexec_pvt.h:271
const OpcodeVec & ops() const
Definition: oslexec_pvt.h:411
ustring closest
double add(double a, double b)
Definition: vm_test.cpp:38
ClosureMul * closure_mul_allot(float w, const ClosureColor *c)
Definition: oslexec_pvt.h:912
long time(time_t *)
ClosureMul * closure_mul_allot(const Color3 &w, const ClosureColor *c)
Definition: oslexec_pvt.h:904
void optimized(int opt)
Definition: oslexec_pvt.h:490
HIDDEN int setup(register struct region *rp, struct bu_vls *matparm, void **dpp, struct rt_i *rtip, char *parameters, struct camo_specific defaults)
Definition: sh_camo.c:205
ustring dPdu
TextureSystem * texturesys() const
Definition: oslexec_pvt.h:655
const ClosureEntry * get_entry(int id) const
Definition: oslexec_pvt.h:558
ParamValueList & messages()
Definition: oslexec_pvt.h:950
ustring width
ustring rwrap
int * alloc_int_constants(size_t n)
Definition: oslexec_pvt.h:671
size_t llvm_groupdata_size() const
Definition: oslexec_pvt.h:492
ustring mirror
ustring twrap
int maincodeend() const
Definition: oslexec_pvt.h:386
ustring swidth
const std::string & shadername() const
Definition: oslexec_pvt.h:315
bool outgoing_connections() const
Definition: oslexec_pvt.h:380
int channel
Channel number (-1 for no channel selection)
Definition: oslexec_pvt.h:273
ustring periodic
COMPLEX data[64]
Definition: fftest.c:34
ShaderUse use() const
Definition: oslexec_pvt.h:891
ustring default_
ustring tblur
Symbol * argsymbol(int argnum)
Definition: oslexec_pvt.h:410
friend std::pair< Symbol *, Symbol * > param_range(ShaderInstance *i)
Definition: oslexec_pvt.h:393
ustring dPdv
int arrayindex
Array index (-1 for not an index)
Definition: oslexec_pvt.h:272
ShadingAttribState * attribs()
Definition: oslexec_pvt.h:946
ustring sidedness
int arg(int argnum)
Definition: oslexec_pvt.h:409
bool run_lazily() const
Definition: oslexec_pvt.h:375
ustring twidth
CompareClosureFunc compare
Definition: oslexec_pvt.h:551
const Symbol * symbol(int index) const
Definition: oslexec_pvt.h:340
ErrorHandler & errhandler() const
Definition: oslexec_pvt.h:623
void does_nothing(bool new_val)
Definition: oslexec_pvt.h:506
value_t requested(void) const
Definition: oslexec_pvt.h:133
ustring smartbicubic
const ConnectionVec & connections() const
Definition: oslexec_pvt.h:363
ustring camera
const SymbolVec & symbols() const
Definition: oslexec_pvt.h:417
off_t vectorbytes(const std::vector< T > &v)
Definition: oslexec_pvt.h:193
goto out
Definition: nmg_mod.c:3846
const ClosureRegistry::ClosureEntry * find_closure(int id) const
Definition: oslexec_pvt.h:683
ustring * alloc_string_constants(size_t n)
Definition: oslexec_pvt.h:673
ShaderMaster * master() const
Definition: oslexec_pvt.h:319
bool writes_globals() const
Definition: oslexec_pvt.h:371
ustring alpha
ShadingSystemImpl & shadingsys() const
Definition: oslexec_pvt.h:877
ustring rblur
RendererServices * renderer() const
Definition: oslexec_pvt.h:651
const std::vector< int > & args() const
Definition: oslexec_pvt.h:407
ShaderMaster(ShadingSystemImpl &shadingsys)
Definition: oslexec_pvt.h:218
std::string memstat() const
Definition: oslexec_pvt.h:179
ustring blur
ConnectedParam dst
Which destination parameter (or part thereof)
Definition: oslexec_pvt.h:288
ustring null
ustring layername() const
Definition: oslexec_pvt.h:311
Symbol * symbol(int index)
Definition: oslexec_pvt.h:239
char * alloc(size_t size)
Definition: oslexec_pvt.h:846
friend std::pair< const Symbol *, const Symbol * > param_range(const ShaderInstance *i)
Definition: oslexec_pvt.h:398
void outgoing_connections(bool out)
Definition: oslexec_pvt.h:383
RendererServices * renderer() const
Definition: oslexec_pvt.h:881
ustring commonspace_synonym() const
Definition: oslexec_pvt.h:664
ustring firstchannel
void changed_shaders()
Called when the shaders of the attrib state change (invalidate LLVM ?)
Definition: oslexec_pvt.h:1017
ustring label
void llvm_groupdata_size(size_t size)
Definition: oslexec_pvt.h:493
value_t peak(void) const
Definition: oslexec_pvt.h:136
SetupClosureFunc setup
Definition: oslexec_pvt.h:550
void run_lazily(bool lazy)
Definition: oslexec_pvt.h:376
ustring front
float * alloc_float_constants(size_t n)
Definition: oslexec_pvt.h:672
shared_ptr< ShaderInstance > ShaderInstanceRef
Definition: oslexec_pvt.h:89
int nkeyword
Definition: oslexec_pvt.h:543
value_t current(void) const
Definition: oslexec_pvt.h:130
ustring object
ShadingSystemImpl & shadingsys() const
Definition: oslexec_pvt.h:225
RunLLVMGroupFunc llvm_compiled_version() const
Definition: oslexec_pvt.h:495
ustring both
ustring cubic
ustring shader
ustring linear
Definition: human.c:197
ustring fill
void stlfree(T &v)
Definition: oslexec_pvt.h:202
int nconnections() const
Definition: oslexec_pvt.h:354
bool lockgeom_default() const
Definition: oslexec_pvt.h:660
int nformal
Definition: oslexec_pvt.h:541
ShaderGroup & shadergroup(ShaderUse use)
Definition: oslexec_pvt.h:1012
void llvm_compiled_version(RunLLVMGroupFunc func)
Definition: oslexec_pvt.h:498
ustring common
Connection(int srclay, const ConnectedParam &srccon, const ConnectedParam &dstcon)
Definition: oslexec_pvt.h:290
ClosureComponent * closure_component_allot(int id, size_t prim_size, int nattrs)
Definition: oslexec_pvt.h:893
long long int executions() const
Definition: oslexec_pvt.h:510
llvm::LLVMContext * llvm_context()
Definition: oslexec_pvt.h:675
int srclayer
Layer (within our group) of the source.
Definition: oslexec_pvt.h:286
PrepareClosureFunc prepare
Definition: oslexec_pvt.h:549