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