1 // Copyright Contributors to the Open Shading Language project.
2 // SPDX-License-Identifier: BSD-3-Clause
3 // https://github.com/AcademySoftwareFoundation/OpenShadingLanguage
4 
5 #pragma once
6 
7 #include <memory>
8 
9 #include <OSL/oslconfig.h>
10 #include <OSL/shaderglobals.h>
11 #include <OSL/rendererservices.h>
12 
13 #include <OpenImageIO/refcnt.h>
14 #include <OpenImageIO/ustring.h>
15 
16 
17 OSL_NAMESPACE_ENTER
18 
19 class RendererServices;
20 class ShaderGroup;
21 typedef std::shared_ptr<ShaderGroup> ShaderGroupRef;
22 struct ClosureParam;
23 struct PerThreadInfo;
24 class ShadingContext;
25 class ShaderSymbol;
26 
27 
28 
29 /// Opaque pointer to whatever the renderer uses to represent a
30 /// (potentially motion-blurred) coordinate transformation.
31 typedef const void* TransformationPtr;
32 
33 
34 // Callbacks for closure creation
35 typedef void (*PrepareClosureFunc)(RendererServices*, int id, void* data);
36 typedef void (*SetupClosureFunc)(RendererServices*, int id, void* data);
37 
38 
39 namespace pvt {
40 class ShadingSystemImpl;
41 }
42 
43 namespace Strings {
44 #ifdef __CUDA_ARCH__
45     #define STRDECL(str,var_name) extern __device__ ustring var_name;
46 #else
47     // Any strings referenced inside of a libsoslexec/wide/*.cpp
48     // or liboslnoise/wide/*.cpp will need OSLEXECPUBLIC
49     #define STRDECL(str,var_name) OSLEXECPUBLIC extern const ustring var_name;
50 #endif
51 #include <OSL/strdecls.h>
52 #undef STRDECL
53 }; // namespace Strings
54 
55 
56 
57 class OSLEXECPUBLIC ShadingSystem
58 {
59 public:
60     ShadingSystem (RendererServices *renderer=NULL,
61                    TextureSystem *texturesystem=NULL,
62                    ErrorHandler *err=NULL);
63     ~ShadingSystem ();
64 
65     /// Set an attribute controlling the shading system.  Return true
66     /// if the name and type were recognized and the attrib was set.
67     /// Documented attributes are as follows:
68     /// 1. Attributes that should be exposed to users:
69     ///    int statistics:level   Automatically print OSL statistics (0).
70     ///    string searchpath:shader  Colon-separated path to search for .oso
71     ///                                files ("", meaning test "." only)
72     ///    string colorspace      Name of RGB color space ("Rec709")
73     ///    int range_checking     Generate extra code for component & array
74     ///                              range checking (1)
75     ///    int debug_nan          Add extra (expensive) code to pinpoint
76     ///                              when NaN/Inf happens (0).
77     ///    int debug_uninit       Add extra (expensive) code to pinpoint
78     ///                              use of uninitialized variables (0).
79     ///    int compile_report     Issue info messages to the renderer for
80     ///                              every shader compiled (0).
81     ///    int max_warnings_per_thread  Number of warning calls that should be
82     ///                              processed per thread (100).
83     ///    int buffer_printf      Buffer printf output from shaders and
84     ///                              output atomically, to prevent threads
85     ///                              from interleaving lines. (1)
86     ///    int profile            Perform some rudimentary profiling (0)
87     ///    int no_noise           Replace noise with constant value. (0)
88     ///    int no_pointcloud      Skip pointcloud lookups. (0)
89     ///    int exec_repeat        How many times to run each group (1).
90     ///    int opt_warnings       Warn on certain failure to runtime-optimize
91     ///                              certain shader constructs. (0)
92     ///    int gpu_opt_error      Consider a hard error if certain shader
93     ///                              constructs cannot be optimized away. (0)
94     /// 2. Attributes that should be set by applications/renderers that
95     /// incorporate OSL:
96     ///    string commonspace     Name of "common" coord system ("world")
97     ///    string[] raytypes      Array of ray type names
98     ///    string[] renderer_outputs
99     ///                           Array of names of renderer outputs (AOVs)
100     ///                              that should not be optimized away.
101     ///    int unknown_coordsys_error  Should errors be issued when unknown
102     ///                              coord system names are used? (1)
103     ///    int connection_error   Should errors be issued when ConnectShaders
104     ///                              fails to find the layer or parameter? (1)
105     ///    int strict_messages    Issue error if a message is set after
106     ///                              being queried (1).
107     ///    int error_repeats      If zero, suppress repeats of errors and
108     ///                              warnings that are exact duplicates of
109     ///                              earlier ones. (1)
110     ///    int lazylayers         Evaluate shader layers only when their
111     ///                              outputs are first needed (1)
112     ///    int lazyglobals        Run layers lazily even if they write to
113     ///                              globals (1)
114     ///    int lazyunconnected    Run layers lazily even if they have no
115     ///                              output connections (1). For debugging.
116     ///    int lazyerror          Run layers lazily even if they have error
117     ///                              ops after optimization (1).
118     ///    int lazy_userdata      Retrieve userdata lazily (0).
119     ///    int userdata_isconnected  Should lockgeom=0 params (that may
120     ///                              receive userdata) return true from
121     ///                              isconnected()? (0)
122     ///    int greedyjit          Optimize and compile all shaders up front,
123     ///                              versus only as needed (0).
124     ///    int llvm_target_host   Target the specific host architecture for
125     ///                              LLVM IR generation. (1)
126     ///    int llvm_jit_fma       Allow fused mul/add (0). This can increase
127     ///                              speed but can change rounding accuracy
128     ///                              (generally by being better), and might
129     ///                              differ by hardware platform.
130     ///    string llvm_jit_target  JIT to a specific ISA: "" or "none" means
131     ///                              no special ops, "x64", "SSE4.2", "AVX",
132     ///                              "AVX2", "AVX2_noFMA", "AVX512",
133     ///                              "AVX512_noFMA", or "host" means to
134     ///                              figure out what the host can do. ("")
135     ///    int llvm_jit_aggressive  Use LLVM "aggressive" JIT mode. (0)
136     ///    int vector_width       Vector width to allow for SIMD ops (4).
137     ///    int llvm_debugging_symbols  When JITing, generate debug symbols
138     ///                             that associate machine code with shader
139     ///                             source and lines. (0)
140     ///    int llvm_profiling_events  When JITing, generate events to enable
141     ///                             full profiling of shaders. (0)
142     ///    int lockgeom           Default 'lockgeom' value for shader params
143     ///                              that don't specify it (1).  Lockgeom
144     ///                              means a param CANNOT be overridden by
145     ///                              interpolated geometric parameters.
146     ///    int countlayerexecs    Add extra code to count total layers run.
147     ///    int allow_shader_replacement Allow shader to be specified more than
148     ///                              once, replacing former definition.
149     ///    string archive_groupname  Name of a group to pickle and archive.
150     ///    string archive_filename   Name of file to save the group archive.
151     /// 3. Attributes that that are intended for developers debugging
152     /// liboslexec itself:
153     /// These attributes may be helpful for liboslexec developers or
154     /// for debugging, but probably not for using OSL in production:
155     ///    int debug              Set debug output level (0)
156     ///    int clearmemory        Zero out working memory before each shade (0)
157     ///    int optimize           Runtime optimization level (2)
158     ///       And there are several int options that, if set to 0, will turn
159     ///       off individual classes of runtime optimizations:
160     ///         opt_simplify_param, opt_constant_fold, opt_stale_assign,
161     ///         opt_elide_useless_ops, opt_elide_unconnected_outputs,
162     ///         opt_peephole, opt_coalesce_temps, opt_assign, opt_mix
163     ///         opt_merge_instances, opt_merge_instance_with_userdata,
164     ///         opt_fold_getattribute, opt_middleman, opt_texture_handle
165     ///         opt_seed_bblock_aliases
166     ///    int opt_passes         Number of optimization passes per layer (10)
167     ///    int llvm_optimize      Which of several LLVM optimize strategies (0)
168     ///    int llvm_debug         Set LLVM extra debug level (0)
169     ///    int llvm_debug_layers  Extra printfs upon entering and leaving
170     ///                              layer functions.
171     ///    int llvm_debug_ops     Extra printfs for each OSL op (helpful
172     ///                              for devs to find crashes)
173     ///    int llvm_output_bitcode  Output the full bitcode for each group,
174     ///                              for debugging. (0)
175     ///    int llvm_dumpasm       Print the CPU assembly code from the JIT (0)
176     ///    string llvm_prune_ir_strategy  Strategy for pruning unnecessary
177     ///                              IR (choices: "prune" [default],
178     ///                              "internalize", or "none").
179     ///    int max_local_mem_KB   Error if shader group needs more than this
180     ///                              much local storage to execute (1024K)
181     ///    string debug_groupname Name of shader group -- debug only this one
182     ///    string debug_layername Name of shader layer -- debug only this one
183     ///    int optimize_nondebug  If 1, fully optimize shaders that are not
184     ///                              designated as the debug shaders.
185     ///    string opt_layername   If set, only optimize the named layer
186     ///    string only_groupname  Compile only this one group (skip all others)
187     ///    int force_derivs       Force all float-based variables to compute
188     ///                              and store derivatives. (0)
189     ///
190     /// Note: the attributes referred to as "string" are actually on the app
191     /// side as ustring or const char* (they have the same data layout), NOT
192     /// std::string!
193     bool attribute (string_view name, TypeDesc type, const void *val);
194 
195     // Shortcuts for common types
attribute(string_view name,int val)196     bool attribute (string_view name, int val) {
197         return attribute (name, TypeDesc::INT, &val);
198     }
attribute(string_view name,float val)199     bool attribute (string_view name, float val) {
200         return attribute (name, TypeDesc::FLOAT, &val);
201     }
attribute(string_view name,double val)202     bool attribute (string_view name, double val) {
203         float f = (float) val;
204         return attribute (name, TypeDesc::FLOAT, &f);
205     }
attribute(string_view name,string_view val)206     bool attribute (string_view name, string_view val) {
207         const char *s = val.c_str();
208         return attribute (name, TypeDesc::STRING, &s);
209     }
210 
211 
212     /// Set an attribute for a specific shader group.  Return true if the
213     /// name and type were recognized and the attrib was set. Documented
214     /// attributes are as follows:
215     ///    string[] renderer_outputs  Array of names of renderer outputs
216     ///                                 (AOVs) specific to this shader group
217     ///                                 that should not be optimized away.
218     ///    string[] entry_layers      Array of names of layers that may be
219     ///                                 callable entry points. They won't
220     ///                                 be elided, but nor will they be
221     ///                                 called unconditionally.
222     ///    int exec_repeat            How many times to run the group (1).
223     ///
224     bool attribute (ShaderGroup *group, string_view name,
225                     TypeDesc type, const void *val);
attribute(ShaderGroup * group,string_view name,int val)226     bool attribute (ShaderGroup *group, string_view name, int val) {
227         return attribute (group, name, TypeDesc::INT, &val);
228     }
attribute(ShaderGroup * group,string_view name,float val)229     bool attribute (ShaderGroup *group, string_view name, float val) {
230         return attribute (group, name, TypeDesc::FLOAT, &val);
231     }
attribute(ShaderGroup * group,string_view name,double val)232     bool attribute (ShaderGroup *group, string_view name, double val) {
233         float f = (float) val;
234         return attribute (group, name, TypeDesc::FLOAT, &f);
235     }
attribute(ShaderGroup * group,string_view name,string_view val)236     bool attribute (ShaderGroup *group, string_view name, string_view val) {
237         const char *s = val.c_str();
238         return attribute (group, name, TypeDesc::STRING, &s);
239     }
240 
241     /// Get the named attribute, store it in value.
242     ///
243     bool getattribute (string_view name, TypeDesc type, void *val);
244 
245     // Shortcuts for common types
getattribute(string_view name,int & val)246     bool getattribute (string_view name, int &val) {
247         return getattribute (name, TypeDesc::INT, &val);
248     }
getattribute(string_view name,float & val)249     bool getattribute (string_view name, float &val) {
250         return getattribute (name, TypeDesc::FLOAT, &val);
251     }
getattribute(string_view name,double & val)252     bool getattribute (string_view name, double &val) {
253         float f;
254         bool ok = getattribute (name, TypeDesc::FLOAT, &f);
255         if (ok)
256             val = f;
257         return ok;
258     }
getattribute(string_view name,char ** val)259     bool getattribute (string_view name, char **val) {
260         return getattribute (name, TypeDesc::STRING, val);
261     }
getattribute(string_view name,ustring & val)262     bool getattribute (string_view name, ustring &val) {
263         return getattribute (name, TypeDesc::STRING, (char **)&val);
264     }
getattribute(string_view name,std::string & val)265     bool getattribute (string_view name, std::string &val) {
266         const char *s = NULL;
267         bool ok = getattribute (name, TypeDesc::STRING, &s);
268         if (ok)
269             val = s;
270         return ok;
271     }
272 
273     /// Get the named attribute about a particular shader group, store it
274     /// in value.  Attributes that are currently documented include:
275     ///   string groupname           The name of the shader group.
276     ///   int num_layers             The number of layers in the group.
277     ///   string[] layer_names       The names of the layers in the group.
278     ///   int num_textures_needed    The number of texture names that are
279     ///                                known to be potentially needed by the
280     ///                                group (after optimization).
281     ///   ptr textures_needed        Retrieves a pointer to the ustring array
282     ///                                containing all textures known to be
283     ///                                needed.
284     ///   int unknown_textures_needed  Nonzero if additional textures may be
285     ///                                needed, whose names can't be known
286     ///                                without actually running the shader.
287     ///   int num_closures_needed    The number of named closures needed.
288     ///   ptr closures_needed        Retrieves a pointer to the ustring array
289     ///                                containing all closures known to be
290     ///                                needed.
291     ///   int unknown_closures_needed  Nonzero if additional closures may be
292     ///                                needed, whose names can't be known
293     ///                                without actually running the shader.
294     ///   int globals_read           Bitfield ("or'ed" SGBits values) of
295     ///                                which ShaderGlobals may be read by
296     ///                                by the shader group.
297     ///   int globals_write         Bitfield ("or'ed" SGBits values) of
298     ///                                which ShaderGlobals may be written by
299     ///                                by the shader group.
300     ///   int num_globals_needed     The number of named globals needed.
301     ///   ptr globals_needed         Retrieves a pointer to the ustring array
302     ///                                containing all globals needed.
303     ///   int num_userdata           The number of "user data" variables
304     ///                                retrieved by the shader.
305     ///   ptr userdata_names         Retrieves a pointer to the array of
306     ///                                ustring holding the userdata names.
307     ///   ptr userdata_types         Retrieves a pointer to the array of
308     ///                                 TypeDesc describing the userdata.
309     ///   ptr userdata_offsets       Retrieves a pointer to the array of
310     ///                                 int describing the userdata offsets
311     ///                                 within the heap.
312     ///   int num_attributes_needed  The number of attribute/scope pairs that
313     ///                                are known to be queried by the group (the
314     ///                                length of the attributes_needed and
315     ///                                attribute_scopes arrays).
316     ///   ptr attributes_needed      Retrieves a pointer to the ustring array
317     ///                                containing the names of the needed attributes.
318     ///	                               Note that if the same attribute
319     ///                                is requested in multiple scopes, it will
320     ///                                appear in the array multiple times - once for
321     ///                                each scope in which is is queried.
322     ///   ptr attribute_scopes       Retrieves a pointer to a ustring array containing
323     ///                                the scopes associated with each attribute query
324     ///                                in the attributes_needed array.
325     ///   int unknown_attributes_needed  Nonzero if additional attributes may be
326     ///                                  needed, whose names will not be known
327     ///                                  until the shader actually runs.
328     ///   int num_renderer_outputs   Number of named renderer outputs.
329     ///   string renderer_outputs[]  List of renderer outputs.
330     ///   int raytype_queries        Bit field of all possible rayquery
331     ///   int num_entry_layers       Number of named entry point layers.
332     ///   string entry_layers[]      List of entry point layers.
333     ///   string pickle              Retrieves a serialized representation
334     ///                                 of the shader group declaration.
335     /// Note: the attributes referred to as "string" are actually on the app
336     /// side as ustring or const char* (they have the same data layout), NOT
337     /// std::string!
338     bool getattribute (ShaderGroup *group, string_view name,
339                        TypeDesc type, void *val);
340     // Shortcuts for common types
getattribute(ShaderGroup * group,string_view name,int & val)341     bool getattribute (ShaderGroup *group, string_view name, int &val) {
342         return getattribute (group, name, TypeDesc::INT, &val);
343     }
getattribute(ShaderGroup * group,string_view name,float & val)344     bool getattribute (ShaderGroup *group, string_view name, float &val) {
345         return getattribute (group, name, TypeDesc::FLOAT, &val);
346     }
getattribute(ShaderGroup * group,string_view name,double & val)347     bool getattribute (ShaderGroup *group, string_view name, double &val) {
348         float f;
349         bool ok = getattribute (group, name, TypeDesc::FLOAT, &f);
350         if (ok)
351             val = f;
352         return ok;
353     }
getattribute(ShaderGroup * group,string_view name,char ** val)354     bool getattribute (ShaderGroup *group, string_view name, char **val) {
355         return getattribute (group, name, TypeDesc::STRING, val);
356     }
getattribute(ShaderGroup * group,string_view name,ustring & val)357     bool getattribute (ShaderGroup *group, string_view name, ustring &val) {
358         return getattribute (group, name, TypeDesc::STRING, (char **)&val);
359     }
getattribute(ShaderGroup * group,string_view name,std::string & val)360     bool getattribute (ShaderGroup *group, string_view name, std::string &val) {
361         const char *s = NULL;
362         bool ok = getattribute (group, name, TypeDesc::STRING, &s);
363         if (ok)
364             val = s;
365         return ok;
366     }
367 
368 
369     /// Load compiled shader (oso) from a memory buffer, overriding
370     /// shader lookups in the shader search path
371     bool LoadMemoryCompiledShader (string_view shadername,
372                                    string_view buffer);
373 
374     // The basic sequence for declaring a shader group looks like this:
375     // ShadingSystem *ss = ...;
376     // ShaderGroupRef group = ss->ShaderGroupBegin (groupname);
377     //    /* First layer - texture lookup shader: */
378     //       /* Specify instance parameter values */
379     //       const char *mapname = "colormap.exr";
380     //       ss->Parameter (*group, "texturename", mapname);
381     //       float blur = 0.001;
382     //       ss->Parameter (*group, "blur", blur);
383     //       Vec3 colorfilter (0.5f, 0.5f, 1.0f);
384     //       ss->Parameter (*group, "colorfilter", TypeDesc::TypeColor,
385     //                      &colorfilter);
386     //    ss->Shader ("surface", "texmap", "texturelayer");
387     //    /* Second layer - generate the BSDF closure: */
388     //       float roughness = 0.05;
389     //       ss->Parameter (*group, "roughness", roughness);
390     //    ss->Shader (*group, "surface", "plastic", "illumlayer");
391     //    /* Make a connection between the layers */
392     //    ss->ConnectShaders (*group, "texturelayer", "Cout",
393     //                       "illumlayer", "Cs");
394     // ss->ShaderGroupEnd (*group);
395 
396     /// Signal the start of a new shader group.  The return value is a
397     /// reference-counted opaque handle to the ShaderGroup.
398     ShaderGroupRef ShaderGroupBegin (string_view groupname = string_view());
399 
400     /// Alternate way to specify a shader group. The group specification
401     /// syntax looks like this: (as a string, all whitespace is equivalent):
402     ///     param <typename> <paramname> <value>... [[hints]] ;
403     ///     shader <shadername> <layername> ;
404     ///     connect <layername>.<paramname> <layername>.<paramname> ;
405     /// For the sake of easy assembling on command lines, a comma ',' may
406     /// substitute for the semicolon as a separator, and the last separator
407     /// before the end of the string is optional.
408     ShaderGroupRef ShaderGroupBegin (string_view groupname,
409                                      string_view shaderusage,
410                                      string_view groupspec = string_view());
411 
412     /// Signal the end of a new shader group.
413     ///
414     bool ShaderGroupEnd (ShaderGroup& group);
415 
416     /// Set a parameter of the next shader that will be added to the group,
417     /// optionally setting the 'lockgeom' metadata for that parameter
418     /// (despite how it may have been set in the shader).  If lockgeom is
419     /// false, it means that this parameter should NOT be considered locked
420     /// against changes by the geometry, and therefore the shader should not
421     /// optimize assuming that the instance value (the 'val' specified by
422     /// this call) is a constant.
423     bool Parameter (ShaderGroup& group, string_view name, TypeDesc t,
424                     const void *val, bool lockgeom=true);
425     // Shortcuts for param passing a single int, float, or string.
426     bool Parameter (ShaderGroup& group, string_view name,
427                     int val, bool lockgeom=true) {
428         return Parameter (group, name, TypeDesc::INT, &val, lockgeom);
429     }
430     bool Parameter (ShaderGroup& group, string_view name,
431                     float val, bool lockgeom=true) {
432         return Parameter (group, name, TypeDesc::FLOAT, &val, lockgeom);
433     }
434     bool Parameter (ShaderGroup& group, string_view name,
435                     const std::string& val, bool lockgeom=true) {
436         const char *s = val.c_str();
437         return Parameter (group, name, TypeDesc::STRING, &s, lockgeom);
438     }
439     bool Parameter (ShaderGroup& group, string_view name,
440                     ustring val, bool lockgeom=true) {
441         return Parameter (group, name, TypeDesc::STRING, (const char**)&val, lockgeom);
442     }
443 
444     /// Append a new shader instance onto the specified group. The shader
445     /// instance will get any pending parameters that were set by
446     /// Parameter() calls since the last Shader() call for the group.
447     bool Shader (ShaderGroup& group, string_view shaderusage,
448                  string_view shadername, string_view layername);
449 
450     /// Connect two shaders within the specified group. The source layer
451     /// must be *upstream* of down destination layer (i.e. source must be
452     /// declared earlier within the shader group). The named parameters must
453     /// be of compatible type -- float to float, color to color, array to
454     /// array of the same length and element type, etc. In general, it is
455     /// permissible to connect type A to type B if and only if it is allowed
456     /// within OSL to assign an A to a B (i.e., if `A = B` is legal). So any
457     /// "triple" may be connected to any other triple, and a float output
458     /// may be connected to a triple input (but not the other way around).
459     /// It is permitted to connect a single component of an aggregate to a
460     /// float and vice versa, for example,
461     ///   `ConnectShaders (group, "lay1", "mycolorout[2]",
462     ///                    "lay2", "myfloatinput")`
463     ///
464     bool ConnectShaders (ShaderGroup &group,
465                          string_view srclayer, string_view srcparam,
466                          string_view dstlayer, string_view dstparam);
467 
468     /// Replace a parameter value in a previously-declared shader group.
469     /// This is meant to called after the ShaderGroupBegin/End, but will
470     /// fail if the shader has already been irrevocably optimized/compiled,
471     /// unless the particular parameter is marked as lockgeom=0 (which
472     /// indicates that it's a parameter that may be overridden by the
473     /// geometric primitive).  This call gives you a way of changing the
474     /// instance value, even if it's not a geometric override.
475     bool ReParameter (ShaderGroup &group,
476                       string_view layername, string_view paramname,
477                       TypeDesc type, const void *val);
478     // Shortcuts for param passing a single int, float, or string.
ReParameter(ShaderGroup & group,string_view layername,string_view paramname,int val)479     bool ReParameter (ShaderGroup &group, string_view layername,
480                       string_view paramname, int val) {
481         return ReParameter (group, layername, paramname, TypeDesc::INT, &val);
482     }
ReParameter(ShaderGroup & group,string_view layername,string_view paramname,float val)483     bool ReParameter (ShaderGroup &group, string_view layername,
484                       string_view paramname, float val) {
485         return ReParameter (group, layername, paramname, TypeDesc::FLOAT, &val);
486     }
ReParameter(ShaderGroup & group,string_view layername,string_view paramname,const std::string & val)487     bool ReParameter (ShaderGroup &group, string_view layername,
488                       string_view paramname, const std::string& val) {
489         const char *s = val.c_str();
490         return ReParameter (group, layername, paramname, TypeDesc::STRING, &s);
491     }
ReParameter(ShaderGroup & group,string_view layername,string_view paramname,ustring val)492     bool ReParameter (ShaderGroup &group, string_view layername,
493                       string_view paramname, ustring val) {
494         return ReParameter (group, layername, paramname, TypeDesc::STRING,
495                             (const char**)&val);
496     }
497 
498     // Non-threadsafe versions of Parameter, Shader, ConnectShaders, and
499     // ShaderGroupEnd. These depend on some persistent state about which
500     // shader group is the "current" one being amended. It's fine to use
501     // that as long as all shader specification is done from one thread only
502     // (or at least that you are sure no two groups are being specified
503     // concurrently). If there is any doubt about that, use the versions
504     // above that take an explicit `ShaderGroup&`, which are thread-safe
505     // and re-entrant.
506     bool Parameter (string_view name, TypeDesc t, const void *val,
507                     bool lockgeom=true);
508     bool Shader (string_view shaderusage, string_view shadername,
509                  string_view layername);
510     bool ConnectShaders (string_view srclayer, string_view srcparam,
511                          string_view dstlayer, string_view dstparam);
512     bool ShaderGroupEnd (void);
513 
514     /// Create a per-thread data needed for shader execution.  It's very
515     /// important for the app to never use a PerThreadInfo from more than
516     /// one thread (and probably a good idea allocate only one PerThreadInfo
517     /// for each renderer thread), and destroy it with destroy_thread_info
518     /// when the thread terminates (and before the ShadingSystem is
519     /// destroyed).
520     PerThreadInfo * create_thread_info();
521 
522     /// Destroy a PerThreadInfo that was allocated by
523     /// create_thread_info().
524     void destroy_thread_info (PerThreadInfo *threadinfo);
525 
526     /// Get a ShadingContext that we can use.  The context is specific to a
527     /// renderer thread, and should never be passed between or shared by
528     /// more than one thread.  The 'threadinfo' parameter should be a
529     /// thread-specific pointer created by create_thread_info.  The context
530     /// can be used to shade many points; a typical usage is to allocate
531     /// just one context per thread and use it for the whole run.
532     ShadingContext *get_context (PerThreadInfo *threadinfo,
533                                  TextureSystem::Perthread *texture_threadinfo=NULL);
534 
535     /// Return a ShadingContext to the pool.
536     ///
537     void release_context (ShadingContext *ctx);
538 
539     /// Execute the shader group in this context. If ctx is NULL, then
540     /// execute will request one (based on the running thread) on its own
541     /// and then return it when it's done.  This is just a wrapper around
542     /// execute_init, execute_layer of the last (presumably group entry)
543     /// layer, and execute_cleanup. If run==false, just do the binding and
544     /// setup, don't actually run the shader.
545     bool execute (ShadingContext &ctx, ShaderGroup &group,
546                   ShaderGlobals &globals, bool run=true);
547 
548     // DEPRECATED(2.0): ctx pointer
549     bool execute (ShadingContext *ctx, ShaderGroup &group,
550                   ShaderGlobals &globals, bool run=true);
551 
552     /// Bind a shader group and globals to the context, in preparation to
553     /// execute, including optimization and JIT of the group (if it has not
554     /// already been done).  If 'run' is true, also run any initialization
555     /// necessary. If 'run' is false, we are not planning to actually
556     /// execute any part of the shader, so do all the usual binding
557     /// preparation, but don't actually run the shader.  Return true if the
558     /// shader executed, false if it did not (including if the shader itself
559     /// was empty).
560     bool execute_init (ShadingContext &ctx, ShaderGroup &group,
561                        ShaderGlobals &globals, bool run=true);
562 
563     /// Execute the layer whose index is specified, in this context. It is
564     /// presumed that execute_init() has already been called, with
565     /// run==true, and that the call to execute_init() returned true. (One
566     /// reason why it might have returned false is if the shader group
567     /// turned out, after optimization, to do nothing.)
568     bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
569                         int layernumber);
570     /// Execute the layer by name.
571     bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
572                         ustring layername);
573     /// Execute the layer that has the given ShaderSymbol as an output.
574     /// (The symbol is one returned by find_symbol()).
575     bool execute_layer (ShadingContext &ctx, ShaderGlobals &globals,
576                         const ShaderSymbol *symbol);
577 
578     /// Signify that the context is done with the current execution of the
579     /// group that was kicked off by execute_init and one or more calls to
580     /// execute_layer.
581     bool execute_cleanup (ShadingContext &ctx);
582 
583     /// Find the named layer within a group and return its index, or -1
584     /// if no such named layer exists.
585     int find_layer (const ShaderGroup &group, ustring layername) const;
586 
587     /// Get a raw pointer to a named symbol (such as you'd need to pull
588     /// out the value of an output parameter).  ctx is the shading
589     /// context (presumably already run), name is the name of the
590     /// symbol.  If found, get_symbol will return the pointer to the
591     /// symbol's data, and type will get the symbol's type.  If the
592     /// symbol is not found, get_symbol will return NULL.
593     /// If you give just a symbol name, it will search for the symbol in all
594     /// layers, last-to-first. If a specific layer is named, it will search
595     /// only that layer. You can specify a layer either by naming it
596     /// separately, or by concatenating "layername.symbolname", but note
597     /// that the latter will involve string manipulation inside get_symbol
598     /// and is much more expensive than specifying them separately.
599     ///
600     /// These are considered somewhat deprecated, in favor of using
601     /// find_symbol(), symbol_typedesc(), and symbol_address().
602     const void* get_symbol (const ShadingContext &ctx, ustring layername,
603                             ustring symbolname, TypeDesc &type) const;
604     const void* get_symbol (const ShadingContext &ctx, ustring symbolname,
605                             TypeDesc &type) const;
606 
607     /// Search for an output symbol by name (and optionally, layer) within
608     /// the optimized shader group. If the symbol is found, return an opaque
609     /// identifying pointer to it, otherwise return NULL. This is somewhat
610     /// expensive because of the name-based search, but once done, you can
611     /// reuse the pointer to the symbol for the lifetime of the group.
612     ///
613     /// If you give just a symbol name, it will search for the symbol in all
614     /// layers, last-to-first. If a specific layer is named, it will search
615     /// only that layer. You can specify a layer either by naming it
616     /// separately, or by concatenating "layername.symbolname", but note
617     /// that the latter will involve string manipulation inside find_symbol
618     /// and is much more expensive than specifying them separately.
619     const ShaderSymbol* find_symbol (const ShaderGroup &group,
620                              ustring layername, ustring symbolname) const;
621     const ShaderSymbol* find_symbol (const ShaderGroup &group,
622                                      ustring symbolname) const;
623 
624     /// Given an opaque ShaderSymbol*, return the TypeDesc describing it.
625     /// Note that a closure will end up with a TypeDesc::UNKNOWN value.
626     TypeDesc symbol_typedesc (const ShaderSymbol *sym) const;
627 
628     /// Given a context (that has executed a shader) and an opaque
629     /// ShaderSymbol*, return the actual memory address where the value of
630     /// the symbol resides within the heap memory of the context. This
631     /// is only valid for the shader execution that had happened immediately
632     /// prior for this context, but it is a very inexpensive operation.
633     const void* symbol_address (const ShadingContext &ctx,
634                                 const ShaderSymbol *sym) const;
635 
636     /// Return the statistics output as a huge string.
637     ///
638     std::string getstats (int level=1) const;
639 
640     void register_closure (string_view name, int id, const ClosureParam *params,
641                            PrepareClosureFunc prepare, SetupClosureFunc setup);
642 
643     /// Query either by name or id an existing closure. If name is non
644     /// NULL it will use it for the search, otherwise id would be used
645     /// and the name will be placed in name if successful. Also return
646     /// pointer to the params array in the last argument. All args are
647     /// optional but at least one of name or id must non NULL.
648     bool query_closure (const char **name, int *id,
649                         const ClosureParam **params);
650 
651     /// For the proposed shader "global" name, return the corresponding
652     /// SGBits enum.
653     static SGBits globals_bit (ustring name);
654 
655     /// For the SGBits value, return the shader "globals" name.
656     static ustring globals_name (SGBits bit);
657 
658     /// For the proposed raytype name, return the bit pattern that
659     /// describes it, or 0 for an unrecognized name.  (This retrieves
660     /// data passed in via attribute("raytypes")).
661     int raytype_bit (ustring name);
662 
663     /// Configure the default raytypes to assume to be on (or off) at optimization
664     /// time for the given group. The raytypes_on gives a bitfield describing which
665     /// ray flags are known to be 1, and raytypes_off describes which ray flags are
666     /// known to be 0. Bits that are not set in either set of flags are not known
667     /// to the optimizer, and will be determined strictly at execution time.
668     void set_raytypes(ShaderGroup *group, int raytypes_on, int raytypes_off);
669 
670     /// Ensure that the group has been optimized and optionally JITed. The ctx pointer
671     /// supplies a ShadingContext to use.
672     void optimize_group (ShaderGroup *group, ShadingContext *ctx, bool do_jit = true);
673 
674     /// Ensure that the group has been optimized and optionally JITed. This is a
675     /// convenience function that simply calls set_raytypes followed by
676     /// optimize_group. The ctx supplies a ShadingContext to use.
677     void optimize_group (ShaderGroup *group, int raytypes_on,
678                          int raytypes_off, ShadingContext *ctx, bool do_jit = true);
679 
680     /// If option "greedyjit" was set, this call will trigger all
681     /// shader groups that have not yet been compiled to do so with the
682     /// specified number of threads (0 means use all available HW cores).
683     void optimize_all_groups (int nthreads=0, bool do_jit = true);
684 
685     /// Return a pointer to the TextureSystem being used.
686     TextureSystem * texturesys () const;
687 
688     /// Return a pointer to the RendererServices being used.
689     RendererServices * renderer () const;
690 
691     /// Archive the entire shader group so that it can be reconstituted
692     /// later.
693     bool archive_shadergroup (ShaderGroup &group, string_view filename);
694 
695     // DEPRECATED(2.0)
696     bool archive_shadergroup (ShaderGroup *group, string_view filename);
697 
698     /// Helper function -- copy or convert a source value (described by
699     /// srctype) to destination (described by dsttype).  The function
700     /// returns true upon success, or false if the types differ in a way
701     /// that cannot be converted.  As a special case, if dst==NULL or
702     /// src==NULL, no copying is performed, and convert_value merely
703     /// returns a bool indicating if the proposed type conversion is
704     /// allowed.
705     ///
706     /// The following type conversions are supported:
707     /// 1. Identical types copy without modification.
708     /// 2. Conversions following the same rules as type casting and
709     /// assignment in OSL itself:
710     ///   int -> float             convert to float
711     ///   int -> triple            convert to float and replicate x3
712     ///   int -> float[4]          convert to float and replicate x4
713     ///   float -> triple          replicate x3
714     ///   float -> float[4]        replicate x4
715     ///   float -> int             truncate like a (int) type cast
716     ///   triple -> triple         copy, regardless of differing vector types
717     /// 3. Additional rules not allowed in OSL source code:
718     ///   float -> float[2]        replicate x2
719     ///   int -> float[2]          convert to float and replicate x2
720     ///   float[2] -> triple       (f[0], f[1], 0)
721     ///   float[4] -> vec4         allow conversion to OIIO type (no vec4 in OSL)
722     ///
723     /// Observation: none of the supported conversions require more
724     /// storage for src than for dst.
725     static bool convert_value(void* dst, TypeDesc dsttype, const void* src,
726                               TypeDesc srctype);
727 
728 private:
729     pvt::ShadingSystemImpl* m_impl;
730 };
731 
732 
733 
734 #ifdef OPENIMAGEIO_IMAGEBUFALGO_H
735 // To keep from polluting all OSL clients with ImageBuf & ROI, only expose
736 // the following declarations if they have included OpenImageIO/imagebufalgo.h.
737 
738 // enum describing where shades are located for shade_image().
739 enum ShadeImageLocations {
740     ShadePixelCenters,  // locate shades at pixel centers: (i+0.5)/res
741     ShadePixelGrid      // locate shades at grid nodes: i/(res-1)
742 };
743 
744 
745 /// Utility to execute a shader group on each pixel in a rectangular region
746 /// of an ImageBuf (which must already be allocated and which must have
747 /// FLOAT pixels).  The output parameters to save are specified by an array
748 /// of ustring values in 'outputs'. If there are multiple outputs, they will
749 /// simply be concatenated channel by channel in the image.
750 ///
751 /// The roi specifies the region of the ImageBuf to shade (defaulting to the
752 /// whole thing), any pixels outside the roi will not be altered.
753 ///
754 /// The 'defaultsg', if non-NULL, provides a template for the default
755 /// ShaderGlobals to use for each point. If not provided, reasonable
756 /// defaults will be chosen.
757 ///
758 /// When shading, P will have the pixel lattice coordinates (i,j,k), and u
759 /// and v will vary from 0->1 across the full (aka "display") window.
760 /// Depending on the value of 'shadelocations', the shading locations
761 /// themselves will either be at "pixel centers" (position (i+0.5)/res), or
762 /// as if it were a grid that is shaded at exact endpoints (position
763 /// i/(res+1)). In either case, derivatives will be set appropriately.
764 OSLEXECPUBLIC
765 bool
766 shade_image(ShadingSystem& shadingsys, ShaderGroup& group,
767             const ShaderGlobals* defaultsg, OIIO::ImageBuf& buf,
768             cspan<ustring> outputs,
769             ShadeImageLocations shadelocations              = ShadePixelCenters,
770             OIIO::ROI roi                                   = OIIO::ROI(),
771             OIIO::parallel_options popt = 0);
772 
773 #endif
774 
775 
776 OSL_NAMESPACE_EXIT
777