diff options
author | Patrick Mours <pmours@nvidia.com> | 2022-09-12 19:46:20 +0300 |
---|---|---|
committer | Patrick Mours <pmours@nvidia.com> | 2022-09-13 11:59:28 +0300 |
commit | a45c36efae07f22dd1da1ebac728324aeafce85e (patch) | |
tree | 842f27474a4b011786da5ef07ed5c6630e8203a9 /intern/cycles/kernel/osl/closures.cpp | |
parent | 8e03df9bbc22baaf9d538e01c44f6857a8c9b43a (diff) |
Cycles: Make OSL implementation independent from SVM
Cleans up the file structure to be more similar to that of the SVM
and also makes it possible to build kernels with OSL support, but
without having to include SVM support.
This patch was split from D15902.
Differential Revision: https://developer.blender.org/D15949
Diffstat (limited to 'intern/cycles/kernel/osl/closures.cpp')
-rw-r--r-- | intern/cycles/kernel/osl/closures.cpp | 258 |
1 files changed, 257 insertions, 1 deletions
diff --git a/intern/cycles/kernel/osl/closures.cpp b/intern/cycles/kernel/osl/closures.cpp index 45ecd5132ef..d56e0551a91 100644 --- a/intern/cycles/kernel/osl/closures.cpp +++ b/intern/cycles/kernel/osl/closures.cpp @@ -20,8 +20,15 @@ #include "kernel/device/cpu/compat.h" #include "kernel/device/cpu/globals.h" +#include "kernel/geom/object.h" +#include "kernel/util/differential.h" + +#include "kernel/osl/osl.h" + #include "kernel/osl/closures_setup.h" -#include "kernel/osl/types.h" + +#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z) +#define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) CCL_NAMESPACE_BEGIN @@ -53,4 +60,253 @@ void OSLRenderServices::register_closures(OSL::ShadingSystem *ss) #include "closures_template.h" } +/* Globals */ + +static void shaderdata_to_shaderglobals(const KernelGlobalsCPU *kg, + ShaderData *sd, + const void *state, + uint32_t path_flag, + OSLThreadData *tdata) +{ + OSL::ShaderGlobals *globals = &tdata->globals; + + const differential3 dP = differential_from_compact(sd->Ng, sd->dP); + const differential3 dI = differential_from_compact(sd->I, sd->dI); + + /* copy from shader data to shader globals */ + globals->P = TO_VEC3(sd->P); + globals->dPdx = TO_VEC3(dP.dx); + globals->dPdy = TO_VEC3(dP.dy); + globals->I = TO_VEC3(sd->I); + globals->dIdx = TO_VEC3(dI.dx); + globals->dIdy = TO_VEC3(dI.dy); + globals->N = TO_VEC3(sd->N); + globals->Ng = TO_VEC3(sd->Ng); + globals->u = sd->u; + globals->dudx = sd->du.dx; + globals->dudy = sd->du.dy; + globals->v = sd->v; + globals->dvdx = sd->dv.dx; + globals->dvdy = sd->dv.dy; + globals->dPdu = TO_VEC3(sd->dPdu); + globals->dPdv = TO_VEC3(sd->dPdv); + globals->surfacearea = 1.0f; + globals->time = sd->time; + + /* booleans */ + globals->raytype = path_flag; + globals->flipHandedness = 0; + globals->backfacing = (sd->flag & SD_BACKFACING); + + /* shader data to be used in services callbacks */ + globals->renderstate = sd; + + /* hacky, we leave it to services to fetch actual object matrix */ + globals->shader2common = sd; + globals->object2common = sd; + + /* must be set to NULL before execute */ + globals->Ci = NULL; + + /* clear trace data */ + tdata->tracedata.init = false; + + /* Used by render-services. */ + sd->osl_globals = kg; + if (path_flag & PATH_RAY_SHADOW) { + sd->osl_path_state = nullptr; + sd->osl_shadow_path_state = (const IntegratorShadowStateCPU *)state; + } + else { + sd->osl_path_state = (const IntegratorStateCPU *)state; + sd->osl_shadow_path_state = nullptr; + } +} + +static void flatten_closure_tree(const KernelGlobalsCPU *kg, + ShaderData *sd, + uint32_t path_flag, + const OSL::ClosureColor *closure, + float3 weight = make_float3(1.0f, 1.0f, 1.0f)) +{ + /* OSL gives us a closure tree, we flatten it into arrays per + * closure type, for evaluation, sampling, etc later on. */ + + switch (closure->id) { + case OSL::ClosureColor::MUL: { + OSL::ClosureMul *mul = (OSL::ClosureMul *)closure; + flatten_closure_tree(kg, sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight); + break; + } + case OSL::ClosureColor::ADD: { + OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure; + flatten_closure_tree(kg, sd, path_flag, add->closureA, weight); + flatten_closure_tree(kg, sd, path_flag, add->closureB, weight); + break; + } +#define OSL_CLOSURE_STRUCT_BEGIN(Upper, lower) \ + case OSL_CLOSURE_##Upper##_ID: { \ + const OSL::ClosureComponent *comp = reinterpret_cast<const OSL::ClosureComponent *>(closure); \ + weight *= TO_FLOAT3(comp->w); \ + osl_closure_##lower##_setup( \ + kg, sd, path_flag, weight, reinterpret_cast<const Upper##Closure *>(comp + 1)); \ + break; \ + } +#include "closures_template.h" + default: + break; + } +} + +/* Surface */ + +void OSLShader::eval_surface(const KernelGlobalsCPU *kg, + const void *state, + ShaderData *sd, + uint32_t path_flag) +{ + /* setup shader globals from shader data */ + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata); + + /* execute shader for this point */ + OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context; + int shader = sd->shader & SHADER_MASK; + + /* automatic bump shader */ + if (kg->osl->bump_state[shader]) { + /* save state */ + const float3 P = sd->P; + const float dP = sd->dP; + const OSL::Vec3 dPdx = globals->dPdx; + const OSL::Vec3 dPdy = globals->dPdy; + + /* set state as if undisplaced */ + if (sd->flag & SD_HAS_DISPLACEMENT) { + float data[9]; + bool found = kg->osl->services->get_attribute(sd, + true, + OSLRenderServices::u_empty, + TypeDesc::TypeVector, + OSLRenderServices::u_geom_undisplaced, + data); + (void)found; + assert(found); + + differential3 tmp_dP; + memcpy(&sd->P, data, sizeof(float) * 3); + memcpy(&tmp_dP.dx, data + 3, sizeof(float) * 3); + memcpy(&tmp_dP.dy, data + 6, sizeof(float) * 3); + + object_position_transform(kg, sd, &sd->P); + object_dir_transform(kg, sd, &tmp_dP.dx); + object_dir_transform(kg, sd, &tmp_dP.dy); + + sd->dP = differential_make_compact(tmp_dP); + + globals->P = TO_VEC3(sd->P); + globals->dPdx = TO_VEC3(tmp_dP.dx); + globals->dPdy = TO_VEC3(tmp_dP.dy); + } + + /* execute bump shader */ + ss->execute(octx, *(kg->osl->bump_state[shader]), *globals); + + /* reset state */ + sd->P = P; + sd->dP = dP; + + globals->P = TO_VEC3(P); + globals->dPdx = TO_VEC3(dPdx); + globals->dPdy = TO_VEC3(dPdy); + } + + /* surface shader */ + if (kg->osl->surface_state[shader]) { + ss->execute(octx, *(kg->osl->surface_state[shader]), *globals); + } + + /* flatten closure tree */ + if (globals->Ci) { + flatten_closure_tree(kg, sd, path_flag, globals->Ci); + } +} + +/* Background */ + +void OSLShader::eval_background(const KernelGlobalsCPU *kg, + const void *state, + ShaderData *sd, + uint32_t path_flag) +{ + /* setup shader globals from shader data */ + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata); + + /* execute shader for this point */ + OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context; + + if (kg->osl->background_state) { + ss->execute(octx, *(kg->osl->background_state), *globals); + } + + /* return background color immediately */ + if (globals->Ci) { + flatten_closure_tree(kg, sd, path_flag, globals->Ci); + } +} + +/* Volume */ + +void OSLShader::eval_volume(const KernelGlobalsCPU *kg, + const void *state, + ShaderData *sd, + uint32_t path_flag) +{ + /* setup shader globals from shader data */ + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, state, path_flag, tdata); + + /* execute shader */ + OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context; + int shader = sd->shader & SHADER_MASK; + + if (kg->osl->volume_state[shader]) { + ss->execute(octx, *(kg->osl->volume_state[shader]), *globals); + } + + /* flatten closure tree */ + if (globals->Ci) { + flatten_closure_tree(kg, sd, path_flag, globals->Ci); + } +} + +/* Displacement */ + +void OSLShader::eval_displacement(const KernelGlobalsCPU *kg, const void *state, ShaderData *sd) +{ + /* setup shader globals from shader data */ + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, state, 0, tdata); + + /* execute shader */ + OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context; + int shader = sd->shader & SHADER_MASK; + + if (kg->osl->displacement_state[shader]) { + ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals); + } + + /* get back position */ + sd->P = TO_FLOAT3(globals->P); +} + CCL_NAMESPACE_END |