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