Blender  V2.93
osl_shader.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2011-2013 Blender Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <OSL/oslexec.h>
18 
19 // clang-format off
22 #include "kernel/kernel_types.h"
24 #include "kernel/kernel_globals.h"
25 
27 
29 #include "kernel/osl/osl_globals.h"
31 #include "kernel/osl/osl_shader.h"
32 // clang-format on
33 
34 #include "util/util_foreach.h"
35 
36 #include "render/attribute.h"
37 
39 
40 /* Threads */
41 
42 void OSLShader::thread_init(KernelGlobals *kg,
43  KernelGlobals *kernel_globals,
44  OSLGlobals *osl_globals)
45 {
46  /* no osl used? */
47  if (!osl_globals->use) {
48  kg->osl = NULL;
49  return;
50  }
51 
52  /* per thread kernel data init*/
53  kg->osl = osl_globals;
54 
55  OSL::ShadingSystem *ss = kg->osl->ss;
56  OSLThreadData *tdata = new OSLThreadData();
57 
58  memset((void *)&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
59  tdata->globals.tracedata = &tdata->tracedata;
60  tdata->globals.flipHandedness = false;
61  tdata->osl_thread_info = ss->create_thread_info();
62  tdata->context = ss->get_context(tdata->osl_thread_info);
63 
64  tdata->oiio_thread_info = osl_globals->ts->get_perthread_info();
65 
66  kg->osl_ss = (OSLShadingSystem *)ss;
67  kg->osl_tdata = tdata;
68 }
69 
70 void OSLShader::thread_free(KernelGlobals *kg)
71 {
72  if (!kg->osl)
73  return;
74 
75  OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
76  OSLThreadData *tdata = kg->osl_tdata;
77  ss->release_context(tdata->context);
78 
79  ss->destroy_thread_info(tdata->osl_thread_info);
80 
81  delete tdata;
82 
83  kg->osl = NULL;
84  kg->osl_ss = NULL;
85  kg->osl_tdata = NULL;
86 }
87 
88 /* Globals */
89 
91  KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, OSLThreadData *tdata)
92 {
93  OSL::ShaderGlobals *globals = &tdata->globals;
94 
95  /* copy from shader data to shader globals */
96  globals->P = TO_VEC3(sd->P);
97  globals->dPdx = TO_VEC3(sd->dP.dx);
98  globals->dPdy = TO_VEC3(sd->dP.dy);
99  globals->I = TO_VEC3(sd->I);
100  globals->dIdx = TO_VEC3(sd->dI.dx);
101  globals->dIdy = TO_VEC3(sd->dI.dy);
102  globals->N = TO_VEC3(sd->N);
103  globals->Ng = TO_VEC3(sd->Ng);
104  globals->u = sd->u;
105  globals->dudx = sd->du.dx;
106  globals->dudy = sd->du.dy;
107  globals->v = sd->v;
108  globals->dvdx = sd->dv.dx;
109  globals->dvdy = sd->dv.dy;
110  globals->dPdu = TO_VEC3(sd->dPdu);
111  globals->dPdv = TO_VEC3(sd->dPdv);
112  globals->surfacearea = 1.0f;
113  globals->time = sd->time;
114 
115  /* booleans */
116  globals->raytype = path_flag;
117  globals->backfacing = (sd->flag & SD_BACKFACING);
118 
119  /* shader data to be used in services callbacks */
120  globals->renderstate = sd;
121 
122  /* hacky, we leave it to services to fetch actual object matrix */
123  globals->shader2common = sd;
124  globals->object2common = sd;
125 
126  /* must be set to NULL before execute */
127  globals->Ci = NULL;
128 
129  /* clear trace data */
130  tdata->tracedata.init = false;
131 
132  /* Used by render-services. */
133  sd->osl_globals = kg;
134  sd->osl_path_state = state;
135 }
136 
137 /* Surface */
138 
140  int path_flag,
141  const OSL::ClosureColor *closure,
142  float3 weight = make_float3(1.0f, 1.0f, 1.0f))
143 {
144  /* OSL gives us a closure tree, we flatten it into arrays per
145  * closure type, for evaluation, sampling, etc later on. */
146 
147  switch (closure->id) {
148  case OSL::ClosureColor::MUL: {
149  OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
150  flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight);
151  break;
152  }
153  case OSL::ClosureColor::ADD: {
154  OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
155  flatten_surface_closure_tree(sd, path_flag, add->closureA, weight);
156  flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
157  break;
158  }
159  default: {
160  OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
161  CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
162 
163  if (prim) {
164 #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
165  weight = weight * TO_FLOAT3(comp->w);
166 #endif
167  prim->setup(sd, path_flag, weight);
168  }
169  break;
170  }
171  }
172 }
173 
174 void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
175 {
176  /* setup shader globals from shader data */
177  OSLThreadData *tdata = kg->osl_tdata;
178  shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
179 
180  /* execute shader for this point */
181  OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
182  OSL::ShaderGlobals *globals = &tdata->globals;
183  OSL::ShadingContext *octx = tdata->context;
184  int shader = sd->shader & SHADER_MASK;
185 
186  /* automatic bump shader */
187  if (kg->osl->bump_state[shader]) {
188  /* save state */
189  float3 P = sd->P;
190  float3 dPdx = sd->dP.dx;
191  float3 dPdy = sd->dP.dy;
192 
193  /* set state as if undisplaced */
194  if (sd->flag & SD_HAS_DISPLACEMENT) {
195  float data[9];
196  bool found = kg->osl->services->get_attribute(sd,
197  true,
199  TypeDesc::TypeVector,
201  data);
202  (void)found;
203  assert(found);
204 
205  memcpy(&sd->P, data, sizeof(float) * 3);
206  memcpy(&sd->dP.dx, data + 3, sizeof(float) * 3);
207  memcpy(&sd->dP.dy, data + 6, sizeof(float) * 3);
208 
209  object_position_transform(kg, sd, &sd->P);
210  object_dir_transform(kg, sd, &sd->dP.dx);
211  object_dir_transform(kg, sd, &sd->dP.dy);
212 
213  globals->P = TO_VEC3(sd->P);
214  globals->dPdx = TO_VEC3(sd->dP.dx);
215  globals->dPdy = TO_VEC3(sd->dP.dy);
216  }
217 
218  /* execute bump shader */
219  ss->execute(octx, *(kg->osl->bump_state[shader]), *globals);
220 
221  /* reset state */
222  sd->P = P;
223  sd->dP.dx = dPdx;
224  sd->dP.dy = dPdy;
225 
226  globals->P = TO_VEC3(P);
227  globals->dPdx = TO_VEC3(dPdx);
228  globals->dPdy = TO_VEC3(dPdy);
229  }
230 
231  /* surface shader */
232  if (kg->osl->surface_state[shader]) {
233  ss->execute(octx, *(kg->osl->surface_state[shader]), *globals);
234  }
235 
236  /* flatten closure tree */
237  if (globals->Ci)
238  flatten_surface_closure_tree(sd, path_flag, globals->Ci);
239 }
240 
241 /* Background */
242 
244  const OSL::ClosureColor *closure,
245  float3 weight = make_float3(1.0f, 1.0f, 1.0f))
246 {
247  /* OSL gives us a closure tree, if we are shading for background there
248  * is only one supported closure type at the moment, which has no evaluation
249  * functions, so we just sum the weights */
250 
251  switch (closure->id) {
252  case OSL::ClosureColor::MUL: {
253  OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
254  flatten_background_closure_tree(sd, mul->closure, weight * TO_FLOAT3(mul->weight));
255  break;
256  }
257  case OSL::ClosureColor::ADD: {
258  OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
259 
260  flatten_background_closure_tree(sd, add->closureA, weight);
261  flatten_background_closure_tree(sd, add->closureB, weight);
262  break;
263  }
264  default: {
265  OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
266  CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
267 
268  if (prim) {
269 #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
270  weight = weight * TO_FLOAT3(comp->w);
271 #endif
272  prim->setup(sd, 0, weight);
273  }
274  break;
275  }
276  }
277 }
278 
279 void OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
280 {
281  /* setup shader globals from shader data */
282  OSLThreadData *tdata = kg->osl_tdata;
283  shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
284 
285  /* execute shader for this point */
286  OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
287  OSL::ShaderGlobals *globals = &tdata->globals;
288  OSL::ShadingContext *octx = tdata->context;
289 
290  if (kg->osl->background_state) {
291  ss->execute(octx, *(kg->osl->background_state), *globals);
292  }
293 
294  /* return background color immediately */
295  if (globals->Ci)
296  flatten_background_closure_tree(sd, globals->Ci);
297 }
298 
299 /* Volume */
300 
302  const OSL::ClosureColor *closure,
303  float3 weight = make_float3(1.0f, 1.0f, 1.0f))
304 {
305  /* OSL gives us a closure tree, we flatten it into arrays per
306  * closure type, for evaluation, sampling, etc later on. */
307 
308  switch (closure->id) {
309  case OSL::ClosureColor::MUL: {
310  OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
311  flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
312  break;
313  }
314  case OSL::ClosureColor::ADD: {
315  OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
316  flatten_volume_closure_tree(sd, add->closureA, weight);
317  flatten_volume_closure_tree(sd, add->closureB, weight);
318  break;
319  }
320  default: {
321  OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
322  CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
323 
324  if (prim) {
325 #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
326  weight = weight * TO_FLOAT3(comp->w);
327 #endif
328  prim->setup(sd, 0, weight);
329  }
330  }
331  }
332 }
333 
334 void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag)
335 {
336  /* setup shader globals from shader data */
337  OSLThreadData *tdata = kg->osl_tdata;
338  shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata);
339 
340  /* execute shader */
341  OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
342  OSL::ShaderGlobals *globals = &tdata->globals;
343  OSL::ShadingContext *octx = tdata->context;
344  int shader = sd->shader & SHADER_MASK;
345 
346  if (kg->osl->volume_state[shader]) {
347  ss->execute(octx, *(kg->osl->volume_state[shader]), *globals);
348  }
349 
350  /* flatten closure tree */
351  if (globals->Ci)
352  flatten_volume_closure_tree(sd, globals->Ci);
353 }
354 
355 /* Displacement */
356 
357 void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, PathState *state)
358 {
359  /* setup shader globals from shader data */
360  OSLThreadData *tdata = kg->osl_tdata;
361 
362  shaderdata_to_shaderglobals(kg, sd, state, 0, tdata);
363 
364  /* execute shader */
365  OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
366  OSL::ShaderGlobals *globals = &tdata->globals;
367  OSL::ShadingContext *octx = tdata->context;
368  int shader = sd->shader & SHADER_MASK;
369 
370  if (kg->osl->displacement_state[shader]) {
371  ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals);
372  }
373 
374  /* get back position */
375  sd->P = TO_FLOAT3(globals->P);
376 }
377 
378 /* Attributes */
379 
380 int OSLShader::find_attribute(KernelGlobals *kg,
381  const ShaderData *sd,
382  uint id,
383  AttributeDescriptor *desc)
384 {
385  /* for OSL, a hash map is used to lookup the attribute by name. */
386  int object = sd->object * ATTR_PRIM_TYPES;
387 
388  OSLGlobals::AttributeMap &attr_map = kg->osl->attribute_map[object];
389  ustring stdname(std::string("geom:") +
390  std::string(Attribute::standard_name((AttributeStandard)id)));
391  OSLGlobals::AttributeMap::const_iterator it = attr_map.find(stdname);
392 
393  if (it != attr_map.end()) {
394  const OSLGlobals::Attribute &osl_attr = it->second;
395  *desc = osl_attr.desc;
396 
397  if (sd->prim == PRIM_NONE && (AttributeElement)osl_attr.desc.element != ATTR_ELEMENT_MESH) {
398  desc->offset = ATTR_STD_NOT_FOUND;
399  return ATTR_STD_NOT_FOUND;
400  }
401 
402  /* return result */
403  if (osl_attr.desc.element == ATTR_ELEMENT_NONE) {
404  desc->offset = ATTR_STD_NOT_FOUND;
405  }
406  return desc->offset;
407  }
408  else {
409  desc->offset = ATTR_STD_NOT_FOUND;
410  return (int)ATTR_STD_NOT_FOUND;
411  }
412 }
413 
unsigned int uint
Definition: BLI_sys_types.h:83
#define MUL(x, y, z)
Definition: RandGen.cpp:47
static void mul(btAlignedObjectArray< T > &items, const Q &value)
static const char * standard_name(AttributeStandard std)
Definition: attribute.cpp:311
virtual void setup(ShaderData *sd, int path_flag, float3 weight)=0
static ustring u_empty
Definition: osl_services.h:306
static ustring u_geom_undisplaced
Definition: osl_services.h:285
ccl_device_inline AttributeDescriptor find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id)
ccl_device_inline void object_position_transform(KernelGlobals *kg, const ShaderData *sd, float3 *P)
Definition: geom_object.h:116
ccl_device_inline void object_dir_transform(KernelGlobals *kg, const ShaderData *sd, float3 *D)
Definition: geom_object.h:178
#define CCL_NAMESPACE_END
#define make_float3(x, y, z)
void KERNEL_FUNCTION_FULL_NAME() shader(KernelGlobals *kg, uint4 *input, float4 *output, int type, int filter, int i, int offset, int sample)
@ SD_HAS_DISPLACEMENT
Definition: kernel_types.h:889
@ SD_BACKFACING
Definition: kernel_types.h:843
AttributeStandard
Definition: kernel_types.h:744
@ ATTR_STD_NOT_FOUND
Definition: kernel_types.h:773
#define PRIM_NONE
Definition: kernel_types.h:60
ShaderData
@ SHADER_MASK
Definition: kernel_types.h:593
AttributeElement
Definition: kernel_types.h:729
@ ATTR_ELEMENT_NONE
Definition: kernel_types.h:730
@ ATTR_ELEMENT_MESH
Definition: kernel_types.h:732
@ ATTR_PRIM_TYPES
Definition: kernel_types.h:726
static float P(float k)
Definition: math_interp.c:41
static ulong state[N]
static void add(GHash *messages, MemArena *memarena, const Message *msg)
Definition: msgfmt.c:268
#define TO_FLOAT3(v)
Definition: osl_closures.h:110
#define TO_VEC3(v)
Definition: osl_closures.h:108
static void flatten_surface_closure_tree(ShaderData *sd, int path_flag, const OSL::ClosureColor *closure, float3 weight=make_float3(1.0f, 1.0f, 1.0f))
Definition: osl_shader.cpp:139
static void flatten_background_closure_tree(ShaderData *sd, const OSL::ClosureColor *closure, float3 weight=make_float3(1.0f, 1.0f, 1.0f))
Definition: osl_shader.cpp:243
static void flatten_volume_closure_tree(ShaderData *sd, const OSL::ClosureColor *closure, float3 weight=make_float3(1.0f, 1.0f, 1.0f))
Definition: osl_shader.cpp:301
static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, PathState *state, int path_flag, OSLThreadData *tdata)
Definition: osl_shader.cpp:90
ShadingSystem
Definition: shader.h:48
static void eval_displacement(SubdivDisplacement *displacement, const int ptex_face_index, const float u, const float v, const float dPdu[3], const float dPdv[3], float r_D[3])