Blender V5.0
kernel/osl/osl.h
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2009-2010 Sony Pictures Imageworks Inc., et al. All Rights Reserved.
2 * SPDX-FileCopyrightText: 2011-2022 Blender Foundation
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 * Adapted code from Open Shading Language. */
7
8#pragma once
9
10/* OSL Shader Engine
11 *
12 * Holds all variables to execute and use OSL shaders from the kernel.
13 */
14
15#ifdef __KERNEL_OPTIX__
18#endif
19
21#include "kernel/osl/types.h"
22
24
26
28 const uint32_t path_flag,
30{
31 const differential3 dP = differential_from_compact(sd->Ng, sd->dP);
32 const differential3 dI = differential_from_compact(sd->wi, sd->dI);
33
34 /* copy from shader data to shader globals */
35 globals->P = sd->P;
36 globals->dPdx = dP.dx;
37 globals->dPdy = dP.dy;
38 globals->I = sd->wi;
39 globals->dIdx = dI.dx;
40 globals->dIdy = dI.dy;
41 globals->N = sd->N;
42 globals->Ng = sd->Ng;
43 globals->u = sd->u;
44 globals->dudx = sd->du.dx;
45 globals->dudy = sd->du.dy;
46 globals->v = sd->v;
47 globals->dvdx = sd->dv.dx;
48 globals->dvdy = sd->dv.dy;
49 globals->dPdu = sd->dPdu;
50 globals->dPdv = sd->dPdv;
51 globals->time = sd->time;
52 globals->dtime = 1.0f;
53 globals->surfacearea = 1.0f;
54 globals->raytype = path_flag;
55 globals->flipHandedness = 0;
56 globals->backfacing = (sd->flag & SD_BACKFACING);
57
58 /* shader data to be used in services callbacks */
59 globals->sd = sd;
60 globals->shadingStateUniform = nullptr;
61 globals->thread_index = 0;
62 globals->shade_index = 0;
63
64 /* hacky, we leave it to services to fetch actual object matrix */
65 globals->shader2common = sd;
66 globals->object2common = sd;
67
68 /* must be set to nullptr before execute */
69 globals->Ci = nullptr;
70}
71
73 ccl_private ShaderData *sd,
74 const uint32_t path_flag,
75 const ccl_private OSLClosure *closure)
76{
77 int stack_size = 0;
78 float3 weight = one_float3();
79 float3 weight_stack[16];
80 const ccl_private OSLClosure *closure_stack[16];
81 int layer_stack_level = -1;
82 float3 layer_albedo = zero_float3();
83
84 while (true) {
85 switch (closure->id) {
86 case OSL_CLOSURE_MUL_ID: {
87 const ccl_private OSLClosureMul *mul = static_cast<const ccl_private OSLClosureMul *>(
88 closure);
89 weight *= mul->weight;
90 closure = mul->closure;
91 continue;
92 }
93 case OSL_CLOSURE_ADD_ID: {
94 if (stack_size >= 16) {
95 kernel_assert(!"Exhausted OSL closure stack");
96 break;
97 }
98 const ccl_private OSLClosureAdd *add = static_cast<const ccl_private OSLClosureAdd *>(
99 closure);
100 closure = add->closureA;
101 weight_stack[stack_size] = weight;
102 closure_stack[stack_size++] = add->closureB;
103 continue;
104 }
105 case OSL_CLOSURE_LAYER_ID: {
106 const ccl_private OSLClosureComponent *comp =
107 static_cast<const ccl_private OSLClosureComponent *>(closure);
108 const ccl_private LayerClosure *layer = reinterpret_cast<const ccl_private LayerClosure *>(
109 comp + 1);
110
111 /* Layer closures may not appear in the top layer subtree of another layer closure. */
112 kernel_assert(layer_stack_level == -1);
113
114 if (layer->top != nullptr) {
115 /* Push base layer onto the stack, will be handled after the top layers */
116 weight_stack[stack_size] = weight;
117 closure_stack[stack_size] = layer->base;
118 /* Start accumulating albedo of the top layers */
119 layer_stack_level = stack_size++;
120 layer_albedo = zero_float3();
121 /* Continue with the top layers */
122 closure = layer->top;
123 }
124 else {
125 /* No top layer, just continue with base. */
126 closure = layer->base;
127 }
128 continue;
129 }
130#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
131 case OSL_CLOSURE_##Upper##_ID: { \
132 ccl_private const OSLClosureComponent *comp = \
133 static_cast<ccl_private const OSLClosureComponent *>(closure); \
134 float3 albedo = one_float3(); \
135 osl_closure_##lower##_setup(kg, \
136 sd, \
137 path_flag, \
138 weight * comp->weight, \
139 reinterpret_cast<ccl_private const Upper##Closure *>(comp + 1), \
140 (layer_stack_level >= 0) ? &albedo : nullptr); \
141 if (layer_stack_level >= 0) { \
142 layer_albedo += albedo; \
143 } \
144 break; \
145 }
146#include "closures_template.h"
147 default:
148 break;
149 }
150
151 /* Pop the next closure from the stack (or return if we're done). */
152 do {
153 if (stack_size == 0) {
154 return;
155 }
156
157 weight = weight_stack[--stack_size];
158 closure = closure_stack[stack_size];
159 if (stack_size == layer_stack_level) {
160 /* We just finished processing the top layers of a Layer closure, so adjust the weight to
161 * account for the layering. */
162 weight = closure_layering_weight(layer_albedo, weight);
163 layer_stack_level = -1;
164 /* If it's fully occluded, skip the base layer we just popped from the stack and grab
165 * the next entry instead. */
166 if (is_zero(weight)) {
167 continue;
168 }
169 }
170 } while (closure == nullptr);
171 }
172}
173
174#ifndef __KERNEL_GPU__
175
176template<ShaderType type>
178 const void *state,
179 ShaderData *sd,
180 uint32_t path_flag);
181
182#else
183
184template<ShaderType type, typename ConstIntegratorGenericState>
186 ConstIntegratorGenericState state,
187 ccl_private ShaderData *sd,
188 const uint32_t path_flag)
189{
190 ShaderGlobals globals;
191 shaderdata_to_shaderglobals(sd, path_flag, &globals);
192
193 const int shader = sd->shader & SHADER_MASK;
194
195# ifdef __KERNEL_OPTIX__
196 uint8_t closure_pool[1024];
197 globals.closure_pool = closure_pool;
198 if (path_flag & PATH_RAY_SHADOW) {
199 globals.shade_index = -state - 1;
200 }
201 else {
202 globals.shade_index = state + 1;
203 }
204
205 /* For surface shaders, we might have an automatic bump shader that needs to be executed before
206 * the main shader to update globals.N. */
207 if constexpr (type == SHADER_TYPE_SURFACE) {
208 if (sd->flag & SD_HAS_BUMP) {
209 /* Save state. */
210 const float3 P = sd->P;
211 const float dP = sd->dP;
212 const packed_float3 dPdx = globals.dPdx;
213 const packed_float3 dPdy = globals.dPdy;
214
215 /* Set position state as if undisplaced. */
216 if (sd->flag & SD_HAS_DISPLACEMENT) {
219
220 dual3 P = primitive_surface_attribute<float3>(kg, sd, desc, true, true);
221
223
224 sd->P = P.val;
226
227 globals.P = sd->P;
228 globals.dPdx = P.dx;
229 globals.dPdy = P.dy;
230
231 /* Set normal as if undisplaced. */
233 if (ndesc.offset != ATTR_STD_NOT_FOUND) {
235 primitive_surface_attribute<float3>(kg, sd, ndesc, false, false).val);
236 object_normal_transform(kg, sd, &N);
237 sd->N = (sd->flag & SD_BACKFACING) ? -N : N;
238 globals.N = sd->N;
239 }
240 }
241
242 /* Execute bump shader. */
243 unsigned int optix_dc_index = 2 /* NUM_CALLABLE_PROGRAM_GROUPS */ + 1 /* camera program */ +
244 (shader + SHADER_TYPE_BUMP * kernel_data.max_shaders);
245 optixDirectCall<void>(optix_dc_index,
246 /* shaderglobals_ptr = */ &globals,
247 /* groupdata_ptr = */ (void *)nullptr,
248 /* userdata_base_ptr = */ (void *)nullptr,
249 /* output_base_ptr = */ (void *)nullptr,
250 /* shadeindex = */ 0,
251 /* interactive_params_ptr */ (void *)nullptr);
252
253 /* Reset state. */
254 sd->P = P;
255 sd->dP = dP;
256
257 /* Apply bump output to sd->N since it's used for shadow terminator logic, for example. */
258 sd->N = globals.N;
259
260 globals.P = P;
261 globals.dPdx = dPdx;
262 globals.dPdy = dPdy;
263 }
264 }
265
266 unsigned int optix_dc_index = 2 /* NUM_CALLABLE_PROGRAM_GROUPS */ + 1 /* camera program */ +
267 (shader + type * kernel_data.max_shaders);
268 optixDirectCall<void>(optix_dc_index,
269 /* shaderglobals_ptr = */ &globals,
270 /* groupdata_ptr = */ (void *)nullptr,
271 /* userdata_base_ptr = */ (void *)nullptr,
272 /* output_base_ptr = */ (void *)nullptr,
273 /* shadeindex = */ 0,
274 /* interactive_params_ptr */ (void *)nullptr);
275# endif
276
277 if constexpr (type == SHADER_TYPE_DISPLACEMENT) {
278 sd->P = globals.P;
279 }
280 else if (globals.Ci) {
281 flatten_closure_tree(kg, sd, path_flag, globals.Ci);
282 }
283}
284
285#endif
286
ccl_device_inline Spectrum closure_layering_weight(const Spectrum layer_albedo, const Spectrum weight)
Definition bsdf_util.h:406
static void mul(btAlignedObjectArray< T > &items, const Q &value)
ccl_device_forceinline float3 dPdx(const ccl_private ShaderData *sd)
ccl_device_forceinline float3 dPdy(const ccl_private ShaderData *sd)
#define kernel_assert(cond)
#define kernel_data
#define ccl_private
const ThreadKernelGlobalsCPU * KernelGlobals
#define ccl_device_inline
#define CCL_NAMESPACE_END
ccl_device_forceinline float differential_make_compact(const float dD)
ccl_device_forceinline differential3 differential_from_compact(const float3 D, const float dD)
ccl_device_inline void object_normal_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private float3 *N)
ccl_device_inline void object_position_transform(KernelGlobals kg, const ccl_private ShaderData *sd, ccl_private T *P)
ccl_device void flatten_closure_tree(KernelGlobals kg, ccl_private ShaderData *sd, const uint32_t path_flag, const ccl_private OSLClosure *closure)
CCL_NAMESPACE_BEGIN ccl_device_inline void shaderdata_to_shaderglobals(ccl_private ShaderData *sd, const uint32_t path_flag, ccl_private ShaderGlobals *globals)
void osl_eval_nodes(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, uint32_t path_flag)
@ OSL_CLOSURE_MUL_ID
@ OSL_CLOSURE_ADD_ID
@ SHADER_TYPE_BUMP
@ SHADER_TYPE_SURFACE
@ SHADER_TYPE_DISPLACEMENT
@ SD_HAS_BUMP
@ SD_HAS_DISPLACEMENT
@ SD_BACKFACING
@ ATTR_STD_NOT_FOUND
@ ATTR_STD_POSITION_UNDISPLACED
@ ATTR_STD_NORMAL_UNDISPLACED
@ PATH_RAY_SHADOW
@ SHADER_MASK
ccl_device_inline bool is_zero(const float2 a)
ccl_device_inline float2 safe_normalize(const float2 a)
ccl_device_inline float3 one_float3()
Definition math_float3.h:26
CCL_NAMESPACE_BEGIN ccl_device_inline float3 zero_float3()
Definition math_float3.h:17
static ulong state[N]
#define N
static void add(blender::Map< std::string, std::string > &messages, Message &msg)
Definition msgfmt.cc:222
CCL_NAMESPACE_BEGIN ccl_device_forceinline dual< T > primitive_surface_attribute(KernelGlobals kg, const ccl_private ShaderData *sd, const AttributeDescriptor desc, const bool dx=false, const bool dy=false)
Definition primitive.h:32
#define ccl_device
static bool find_attribute(const std::string &attributes, const char *search_attribute)
ccl_private OSLClosure * Ci
packed_float3 dPdx
packed_float3 N
packed_float3 dPdy
packed_float3 P
dual< float3 > dual3
Definition types_dual.h:58