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 <OSL/oslconfig.h>
8 #include <cstring>
9 
10 OSL_NAMESPACE_ENTER
11 
12 /// Labels for light walks
13 ///
14 /// This is the leftover of a class which used to hold all the labels
15 /// Now just acts as a little namespace for the basic definitions
16 ///
17 /// NOTE: you still can assign these labels as keyword arguments to
18 ///       closures. But we have removed the old labels array in the
19 ///       primitives.
20 class OSLEXECPUBLIC Labels {
21 public:
22     static const ustring NONE;
23     // Event type
24     static const ustring CAMERA;
25     static const ustring LIGHT;
26     static const ustring BACKGROUND;
27     static const ustring TRANSMIT;
28     static const ustring REFLECT;
29     static const ustring VOLUME;
30     static const ustring OBJECT;
31     // Scattering
32     static const ustring DIFFUSE;   // typical 2PI hemisphere
33     static const ustring GLOSSY;    // blurry reflections and transmissions
34     static const ustring SINGULAR;  // perfect mirrors and glass
35     static const ustring STRAIGHT;  // Special case for transparent shadows
36 
37     static const ustring STOP;  // end of a surface description
38 };
39 
40 // Forward declarations
41 struct ClosureComponent;
42 struct ClosureMul;
43 struct ClosureAdd;
44 
45 /// ClosureColor is the base class for a lightweight tree representation
46 /// of OSL closures for the sake of the executing OSL shader.
47 ///
48 /// Remember that a closure color really just boils down to a flat list
49 /// of weighted closure primitive components (such as diffuse,
50 /// transparent, etc.).  But it's expensive to construct these
51 /// dynamically as we execute the shader, so instead of maintaining a
52 /// properly flattened list as we go, we just manipulate a very
53 /// lightweight data structure that looks like a tree, where leaf nodes
54 /// are a single primitive component, and internal nodes of the tree are
55 /// are either 'add' (two closures) or 'mul' (of a closure with a
56 /// weight) and just reference their operands by pointers.
57 ///
58 /// We are extremely careful to make these classes resemble POD (plain
59 /// old data) so they can be easily "placed" anywhere, including a memory
60 /// pool.  So no virtual functions!
61 ///
62 /// The base class ClosureColor just provides the type, and it's
63 /// definitely one of the three kinds of subclasses: ClosureComponent,
64 /// ClosureMul, ClosureAdd.
65 struct OSLEXECPUBLIC ClosureColor {
66     enum ClosureID { COMPONENT_BASE_ID = 0, MUL = -1, ADD = -2 };
67 
68     int id;
69 
as_compClosureColor70     OSL_HOSTDEVICE const ClosureComponent* as_comp() const
71     {
72         OSL_DASSERT(id >= COMPONENT_BASE_ID);
73         return reinterpret_cast<const ClosureComponent*>(this);
74     }
75 
as_mulClosureColor76     OSL_HOSTDEVICE const ClosureMul* as_mul() const
77     {
78         OSL_DASSERT(id == MUL);
79         return reinterpret_cast<const ClosureMul*>(this);
80     }
81 
as_addClosureColor82     OSL_HOSTDEVICE const ClosureAdd* as_add() const
83     {
84         OSL_DASSERT(id == ADD);
85         return reinterpret_cast<const ClosureAdd*>(this);
86     }
87 };
88 
89 
90 
91 /// ClosureComponent is a subclass of ClosureColor that holds the ID and
92 /// parameter data for a single primitive closure component (such as
93 /// diffuse, translucent, etc.).
94 ///
95 /// ClosureComponent itself takes up 16 bytes, and its allocation will be
96 /// scaled to add parameters after the end of the struct. Alignment is
97 /// set to 16 bytes so that 64 bit pointers and 128 bit SSE types in user
98 /// structs have the required alignment.
99 #ifdef __CUDACC__
100 /// Notice in the OptiX implementation we align this to 8 bytes
101 /// so that it matches the alignment of the memory pools.
102 struct OSLEXECPUBLIC
103 OSL_ALIGNAS(8) ClosureComponent : public ClosureColor
104 #else
105 struct OSLEXECPUBLIC
106 OSL_ALIGNAS(16) ClosureComponent : public ClosureColor
107 #endif
108 {
109     Vec3 w;  ///< Weight of this component
110 
111     /// Handy method for getting the parameter memory as a void*.
dataClosureComponent112     OSL_HOSTDEVICE void* data() { return (char*)(this + 1); }
dataClosureComponent113     OSL_HOSTDEVICE const void* data() const { return (const char*)(this + 1); }
114 
115     /// Handy methods for extracting the underlying parameters as a struct
asClosureComponent116     template<typename T> OSL_HOSTDEVICE const T* as() const
117     {
118         return reinterpret_cast<const T*>(data());
119     }
120 
asClosureComponent121     template<typename T> OSL_HOSTDEVICE T* as()
122     {
123         return reinterpret_cast<const T*>(data());
124     }
125 };
126 
127 
128 /// ClosureMul is a subclass of ClosureColor that provides a lightweight
129 /// way to represent a closure multiplied by a scalar or color weight.
130 struct OSLEXECPUBLIC ClosureMul : public ClosureColor {
131     Color3 weight;
132     const ClosureColor* closure;
133 };
134 
135 
136 /// ClosureAdd is a subclass of ClosureColor that provides a lightweight
137 /// way to represent a closure that is a sum of two other closures.
138 struct OSLEXECPUBLIC ClosureAdd : public ClosureColor {
139     const ClosureColor* closureA;
140     const ClosureColor* closureB;
141 };
142 
143 OSL_NAMESPACE_EXIT
144