Blender V5.0
closures.cpp
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#include <OSL/genclosure.h>
9#include <OSL/oslclosure.h>
10
11#include "kernel/types.h"
12
13#include "kernel/osl/globals.h"
14#include "kernel/osl/services.h"
15
16#include "util/math.h"
17#include "util/param.h"
18
19#include "kernel/globals.h"
20
22#include "kernel/geom/object.h"
25
26#include "kernel/osl/camera.h"
27#include "kernel/osl/osl.h"
28
29#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z)
30#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
31
33
34static_assert(sizeof(OSLClosure) == sizeof(OSL::ClosureColor) &&
35 sizeof(OSLClosureAdd) == sizeof(OSL::ClosureAdd) &&
36 sizeof(OSLClosureMul) == sizeof(OSL::ClosureMul) &&
37 sizeof(OSLClosureComponent) == sizeof(OSL::ClosureComponent));
38static_assert(sizeof(ShaderGlobals) >= sizeof(OSL::ShaderGlobals) &&
39 offsetof(ShaderGlobals, backfacing) == offsetof(OSL::ShaderGlobals, backfacing));
40
41/* Registration */
42
43#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
44 static OSL::ClosureParam *osl_closure_##lower##_params() \
45 { \
46 static OSL::ClosureParam params[] = {
47#define OSL_CLOSURE_STRUCT_END(Upper, lower) \
48 CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), CLOSURE_FINISH_PARAM(Upper##Closure) \
49 } \
50 ; \
51 return params; \
52 }
53#define OSL_CLOSURE_STRUCT_MEMBER(Upper, TYPE, type, name, key) \
54 CLOSURE_##TYPE##_KEYPARAM(Upper##Closure, name, key),
55#define OSL_CLOSURE_STRUCT_ARRAY_MEMBER(Upper, TYPE, type, name, key, size) \
56 CLOSURE_##TYPE##_ARRAY_PARAM(Upper##Closure, name, size),
57
58#include "closures_template.h"
59
60static OSL::ClosureParam *osl_closure_layer_params()
61{
62 static OSL::ClosureParam params[] = {CLOSURE_CLOSURE_PARAM(LayerClosure, top),
63 CLOSURE_CLOSURE_PARAM(LayerClosure, base),
64 CLOSURE_FINISH_PARAM(LayerClosure)};
65 return params;
66}
67
68void OSLRenderServices::register_closures(OSL::ShadingSystem *ss)
69{
70#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \
71 ss->register_closure( \
72 #lower, OSL_CLOSURE_##Upper##_ID, osl_closure_##lower##_params(), nullptr, nullptr);
73
74#include "closures_template.h"
75 ss->register_closure(
76 "layer", OSL_CLOSURE_LAYER_ID, osl_closure_layer_params(), nullptr, nullptr);
77}
78
79/* Surface & Background */
80
81template<>
83 const void *state,
84 ShaderData *sd,
85 const uint32_t path_flag)
86{
87 /* setup shader globals from shader data */
88 shaderdata_to_shaderglobals(sd, path_flag, &kg->osl.shader_globals);
89
90 /* clear trace data */
91 kg->osl.tracedata.init = false;
92
93 /* Used by render-services. */
94 kg->osl.shader_globals.kg = kg;
95 if (path_flag & PATH_RAY_SHADOW) {
96 kg->osl.shader_globals.path_state = nullptr;
97 kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
98 }
99 else {
100 kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
101 kg->osl.shader_globals.shadow_path_state = nullptr;
102 }
103
104 /* execute shader for this point */
105 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
106 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
107 OSL::ShadingContext *octx = kg->osl.context;
108 const int shader = sd->shader & SHADER_MASK;
109
110 if (sd->object == OBJECT_NONE) {
111 /* background */
112 if (kg->osl.globals->background_state) {
113 ss->execute(*octx,
114 *(kg->osl.globals->background_state),
115 kg->osl.thread_index,
116 0,
117 *globals,
118 nullptr,
119 nullptr);
120 }
121 }
122 else {
123 /* automatic bump shader */
124 if (kg->osl.globals->bump_state[shader]) {
125 /* save state */
126 const float3 P = sd->P;
127 const float dP = sd->dP;
128 const OSL::Vec3 dPdx = globals->dPdx;
129 const OSL::Vec3 dPdy = globals->dPdy;
130
131 /* set state as if undisplaced */
132 if (sd->flag & SD_HAS_DISPLACEMENT) {
135
136 dual3 P = primitive_surface_attribute<float3>(kg, sd, desc, true, true);
138
139 sd->P = P.val;
141
142 globals->P = TO_VEC3(sd->P);
143 globals->dPdx = TO_VEC3(P.dx);
144 globals->dPdy = TO_VEC3(P.dy);
145
146 /* Set normal as if undisplaced. */
148 if (ndesc.offset != ATTR_STD_NOT_FOUND) {
150 primitive_surface_attribute<float3>(kg, sd, ndesc, false, false).val);
151 object_normal_transform(kg, sd, &N);
152 sd->N = (sd->flag & SD_BACKFACING) ? -N : N;
153 globals->N = TO_VEC3(sd->N);
154 }
155 }
156
157 /* execute bump shader */
158 ss->execute(*octx,
159 *(kg->osl.globals->bump_state[shader]),
160 kg->osl.thread_index,
161 0,
162 *globals,
163 nullptr,
164 nullptr);
165
166 /* reset state */
167 sd->P = P;
168 sd->dP = dP;
169
170 /* Apply bump output to sd->N since it's used for shadow terminator logic, for example. */
171 sd->N = TO_FLOAT3(globals->N);
172
173 globals->P = TO_VEC3(P);
174 globals->dPdx = TO_VEC3(dPdx);
175 globals->dPdy = TO_VEC3(dPdy);
176 }
177
178 /* surface shader */
179 if (kg->osl.globals->surface_state[shader]) {
180 ss->execute(*octx,
181 *(kg->osl.globals->surface_state[shader]),
182 kg->osl.thread_index,
183 0,
184 *globals,
185 nullptr,
186 nullptr);
187 }
188 }
189
190 /* flatten closure tree */
191 if (kg->osl.shader_globals.Ci) {
192 flatten_closure_tree(kg, sd, path_flag, kg->osl.shader_globals.Ci);
193 }
194}
195
196/* Volume */
197
198template<>
200 const void *state,
201 ShaderData *sd,
202 const uint32_t path_flag)
203{
204 /* setup shader globals from shader data */
205 shaderdata_to_shaderglobals(sd, path_flag, &kg->osl.shader_globals);
206
207 /* clear trace data */
208 kg->osl.tracedata.init = false;
209
210 /* Used by render-services. */
211 kg->osl.shader_globals.kg = kg;
212 if (path_flag & PATH_RAY_SHADOW) {
213 kg->osl.shader_globals.path_state = nullptr;
214 kg->osl.shader_globals.shadow_path_state = (const IntegratorShadowStateCPU *)state;
215 }
216 else {
217 kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
218 kg->osl.shader_globals.shadow_path_state = nullptr;
219 }
220
221 /* execute shader */
222 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
223 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
224 OSL::ShadingContext *octx = kg->osl.context;
225 const int shader = sd->shader & SHADER_MASK;
226
227 if (kg->osl.globals->volume_state[shader]) {
228 ss->execute(*octx,
229 *(kg->osl.globals->volume_state[shader]),
230 kg->osl.thread_index,
231 0,
232 *globals,
233 nullptr,
234 nullptr);
235 }
236
237 /* flatten closure tree */
238 if (kg->osl.shader_globals.Ci) {
239 flatten_closure_tree(kg, sd, path_flag, kg->osl.shader_globals.Ci);
240 }
241}
242
243/* Displacement */
244
245template<>
247 const void *state,
248 ShaderData *sd,
249 const uint32_t path_flag)
250{
251 /* setup shader globals from shader data */
252 shaderdata_to_shaderglobals(sd, path_flag, &kg->osl.shader_globals);
253
254 /* clear trace data */
255 kg->osl.tracedata.init = false;
256
257 /* Used by render-services. */
258 kg->osl.shader_globals.kg = kg;
259 kg->osl.shader_globals.path_state = (const IntegratorStateCPU *)state;
260 kg->osl.shader_globals.shadow_path_state = nullptr;
261
262 /* execute shader */
263 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
264 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
265 OSL::ShadingContext *octx = kg->osl.context;
266 const int shader = sd->shader & SHADER_MASK;
267
268 if (kg->osl.globals->displacement_state[shader]) {
269 ss->execute(*octx,
270 *(kg->osl.globals->displacement_state[shader]),
271 kg->osl.thread_index,
272 0,
273 *globals,
274 nullptr,
275 nullptr);
276 }
277
278 /* get back position */
279 sd->P = TO_FLOAT3(globals->P);
280}
281
282/* Camera */
283
285 const packed_float3 sensor,
286 const packed_float3 dSdx,
287 const packed_float3 dSdy,
288 const float2 rand_lens,
293 packed_float3 &dDdx,
294 packed_float3 &dDdy)
295{
296 if (!kg->osl.globals->camera_state) {
297 return zero_spectrum();
298 }
299
300 /* Setup shader globals from the sensor position. */
301 cameradata_to_shaderglobals(sensor, dSdx, dSdy, rand_lens, &kg->osl.shader_globals);
302
303 /* Clear trace data. */
304 kg->osl.tracedata.init = false;
305
306 /* Provide kernel globals to the render-services. */
307 kg->osl.shader_globals.kg = kg;
308
309 /* Execute the shader. */
310 OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl.ss;
311 OSL::ShaderGlobals *globals = reinterpret_cast<OSL::ShaderGlobals *>(&kg->osl.shader_globals);
312 OSL::ShadingContext *octx = kg->osl.context;
313
314 float output[21] = {0.0f};
315
316 ss->execute(
317 *octx, *kg->osl.globals->camera_state, kg->osl.thread_index, 0, *globals, nullptr, output);
318
319 P = make_float3(output[0], output[1], output[2]);
320 dPdx = make_float3(output[3], output[4], output[5]);
321 dPdy = make_float3(output[6], output[7], output[8]);
322 D = make_float3(output[9], output[10], output[11]);
323 dDdx = make_float3(output[12], output[13], output[14]);
324 dDdy = make_float3(output[15], output[16], output[17]);
325 return make_float3(output[18], output[19], output[20]);
326}
327
#define D
static void register_closures(OSL::ShadingSystem *ss)
Definition closures.cpp:68
packed_float3 osl_eval_camera(const ThreadKernelGlobalsCPU *kg, const packed_float3 sensor, const packed_float3 dSdx, const packed_float3 dSdy, const float2 rand_lens, packed_float3 &P, packed_float3 &dPdx, packed_float3 &dPdy, packed_float3 &D, packed_float3 &dDdx, packed_float3 &dDdy)
Definition closures.cpp:284
void osl_eval_nodes< SHADER_TYPE_DISPLACEMENT >(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, const uint32_t path_flag)
Definition closures.cpp:246
void osl_eval_nodes< SHADER_TYPE_VOLUME >(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, const uint32_t path_flag)
Definition closures.cpp:199
void osl_eval_nodes< SHADER_TYPE_SURFACE >(const ThreadKernelGlobalsCPU *kg, const void *state, ShaderData *sd, const uint32_t path_flag)
Definition closures.cpp:82
#define TO_FLOAT3(v)
Definition closures.cpp:30
static OSL::ClosureParam * osl_closure_layer_params()
Definition closures.cpp:60
#define TO_VEC3(v)
Definition closures.cpp:29
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 zero_spectrum
#define OBJECT_NONE
#define CCL_NAMESPACE_END
ccl_device_forceinline float3 make_float3(const float x, const float y, const float z)
#define offsetof(t, d)
ccl_device_forceinline float differential_make_compact(const float dD)
uint top
#define output
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
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_NAMESPACE_BEGIN ccl_device_inline void cameradata_to_shaderglobals(const packed_float3 sensor, const packed_float3 dSdx, const packed_float3 dSdy, const float2 rand_lens, ccl_private ShaderGlobals *globals)
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)
@ 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 float2 safe_normalize(const float2 a)
static ulong state[N]
#define N
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
static bool find_attribute(const std::string &attributes, const char *search_attribute)
dual< float3 > dual3
Definition types_dual.h:58