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
This commit is contained in:
Patrick Mours 2022-09-12 18:46:20 +02:00
parent 8e03df9bbc
commit a45c36efae
20 changed files with 368 additions and 469 deletions

View File

@ -28,7 +28,6 @@
#include "kernel/device/cpu/kernel.h"
#include "kernel/types.h"
#include "kernel/osl/shader.h"
#include "kernel/osl/globals.h"
// clang-format on

View File

@ -23,7 +23,6 @@
#include "kernel/device/cpu/kernel.h"
#include "kernel/device/cpu/globals.h"
#include "kernel/osl/shader.h"
#include "kernel/osl/globals.h"
// clang-format on

View File

@ -3,10 +3,7 @@
#include "device/cpu/kernel_thread_globals.h"
// clang-format off
#include "kernel/osl/shader.h"
#include "kernel/osl/globals.h"
// clang-format on
#include "util/profiling.h"
@ -20,7 +17,7 @@ CPUKernelThreadGlobals::CPUKernelThreadGlobals(const KernelGlobalsCPU &kernel_gl
reset_runtime_memory();
#ifdef WITH_OSL
OSLShader::thread_init(this, reinterpret_cast<OSLGlobals *>(osl_globals_memory));
OSLGlobals::thread_init(this, static_cast<OSLGlobals *>(osl_globals_memory));
#else
(void)osl_globals_memory;
#endif
@ -35,7 +32,7 @@ CPUKernelThreadGlobals::CPUKernelThreadGlobals(CPUKernelThreadGlobals &&other) n
CPUKernelThreadGlobals::~CPUKernelThreadGlobals()
{
#ifdef WITH_OSL
OSLShader::thread_free(this);
OSLGlobals::thread_free(this);
#endif
}

View File

@ -544,8 +544,6 @@ if(WITH_CYCLES_CUDA_BINARIES)
cycles_set_solution_folder(cycles_kernel_cuda)
endif()
####################################################### START
# HIP module
if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
@ -620,7 +618,6 @@ if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
cycles_set_solution_folder(cycles_kernel_hip)
endif()
####################################################### END
# OptiX PTX modules
if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES)
@ -712,6 +709,8 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES)
cycles_set_solution_folder(cycles_kernel_optix)
endif()
# oneAPI module
if(WITH_CYCLES_DEVICE_ONEAPI)
if(WIN32)
set(cycles_kernel_oneapi_lib ${CMAKE_CURRENT_BINARY_DIR}/cycles_kernel_oneapi.dll)

View File

@ -116,7 +116,7 @@ ccl_device_inline int bsdf_sample(KernelGlobals kg,
case CLOSURE_BSDF_DIFFUSE_ID:
label = bsdf_diffuse_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
break;
#ifdef __SVM__
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
label = bsdf_oren_nayar_sample(sc, Ng, sd->I, randu, randv, eval, omega_in, pdf);
break;
@ -246,7 +246,7 @@ ccl_device_inline
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf);
break;
#ifdef __SVM__
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf);
break;
@ -337,7 +337,7 @@ ccl_device_inline
case CLOSURE_BSDF_DIFFUSE_ID:
eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf);
break;
#ifdef __SVM__
#if defined(__SVM__) || defined(__OSL__)
case CLOSURE_BSDF_OREN_NAYAR_ID:
eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf);
break;
@ -419,7 +419,7 @@ ccl_device_inline
ccl_device void bsdf_blur(KernelGlobals kg, ccl_private ShaderClosure *sc, float roughness)
{
/* TODO: do we want to blur volume closures? */
#ifdef __SVM__
#if defined(__SVM__) || defined(__OSL__)
switch (sc->type) {
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_ID:
case CLOSURE_BSDF_MICROFACET_MULTI_GGX_FRESNEL_ID:

View File

@ -5,6 +5,8 @@
#include "kernel/geom/geom.h"
#include "kernel/camera/camera.h"
#include "kernel/film/cryptomatte_passes.h"
#include "kernel/film/write.h"

View File

@ -7,6 +7,8 @@
#pragma once
#include "kernel/util/differential.h"
CCL_NAMESPACE_BEGIN
/* ShaderData setup from incoming ray */

View File

@ -5,10 +5,11 @@
#pragma once
#include "kernel/svm/svm.h"
#ifdef __SVM__
# include "kernel/svm/svm.h"
#endif
#ifdef __OSL__
# include "kernel/osl/shader.h"
# include "kernel/osl/osl.h"
#endif
CCL_NAMESPACE_BEGIN
@ -22,17 +23,18 @@ ccl_device void displacement_shader_eval(KernelGlobals kg,
sd->num_closure_left = 0;
/* this will modify sd->P */
#ifdef __SVM__
# ifdef __OSL__
if (kg->osl)
#ifdef __OSL__
if (kg->osl) {
OSLShader::eval_displacement(kg, state, sd);
}
else
# endif
#endif
{
#ifdef __SVM__
svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_DISPLACEMENT, SHADER_TYPE_DISPLACEMENT>(
kg, state, sd, NULL, 0);
}
#endif
}
}
CCL_NAMESPACE_END

View File

@ -12,8 +12,6 @@
#include "kernel/light/light.h"
#include "kernel/util/differential.h"
#include "kernel/geom/geom.h"
#include "kernel/bvh/bvh.h"

View File

@ -10,10 +10,11 @@
#include "kernel/closure/bsdf_util.h"
#include "kernel/closure/emissive.h"
#include "kernel/svm/svm.h"
#ifdef __SVM__
# include "kernel/svm/svm.h"
#endif
#ifdef __OSL__
# include "kernel/osl/shader.h"
# include "kernel/osl/osl.h"
#endif
CCL_NAMESPACE_BEGIN

View File

@ -10,10 +10,11 @@
#include "kernel/closure/bsdf_util.h"
#include "kernel/closure/emissive.h"
#include "kernel/svm/svm.h"
#ifdef __SVM__
# include "kernel/svm/svm.h"
#endif
#ifdef __OSL__
# include "kernel/osl/shader.h"
# include "kernel/osl/osl.h"
#endif
CCL_NAMESPACE_BEGIN
@ -326,18 +327,18 @@ ccl_device_inline void volume_shader_eval(KernelGlobals kg,
}
/* evaluate shader */
# ifdef __SVM__
# ifdef __OSL__
# ifdef __OSL__
if (kg->osl) {
OSLShader::eval_volume(kg, state, sd, path_flag);
}
else
# endif
# endif
{
# ifdef __SVM__
svm_eval_nodes<KERNEL_FEATURE_NODE_MASK_VOLUME, SHADER_TYPE_VOLUME>(
kg, state, sd, NULL, path_flag);
}
# endif
}
/* Merge closures to avoid exceeding number of closures limit. */
if (!shadow) {

View File

@ -11,16 +11,17 @@ set(INC_SYS
set(SRC
closures.cpp
globals.cpp
services.cpp
shader.cpp
)
set(HEADER_SRC
closures_setup.h
closures_template.h
globals.h
osl.h
services.h
shader.h
types.h
)
set(LIB

View File

@ -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

View File

@ -0,0 +1,59 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include <OSL/oslexec.h>
#include "kernel/device/cpu/compat.h"
#include "kernel/device/cpu/globals.h"
#include "kernel/types.h"
#include "kernel/osl/globals.h"
#include "kernel/osl/services.h"
CCL_NAMESPACE_BEGIN
void OSLGlobals::thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals)
{
/* no osl used? */
if (!osl_globals->use) {
kg->osl = NULL;
return;
}
/* Per thread kernel data init. */
kg->osl = osl_globals;
OSL::ShadingSystem *ss = kg->osl->ss;
OSLThreadData *tdata = new OSLThreadData();
memset((void *)&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
tdata->globals.tracedata = &tdata->tracedata;
tdata->osl_thread_info = ss->create_thread_info();
tdata->context = ss->get_context(tdata->osl_thread_info);
tdata->oiio_thread_info = osl_globals->ts->get_perthread_info();
kg->osl_ss = (OSLShadingSystem *)ss;
kg->osl_tdata = tdata;
}
void OSLGlobals::thread_free(KernelGlobalsCPU *kg)
{
if (!kg->osl)
return;
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
OSLThreadData *tdata = kg->osl_tdata;
ss->release_context(tdata->context);
ss->destroy_thread_info(tdata->osl_thread_info);
delete tdata;
kg->osl = NULL;
kg->osl_ss = NULL;
kg->osl_tdata = NULL;
}
CCL_NAMESPACE_END

View File

@ -41,6 +41,10 @@ struct OSLGlobals {
use = false;
}
/* per thread data */
static void thread_init(struct KernelGlobalsCPU *kg, OSLGlobals *osl_globals);
static void thread_free(struct KernelGlobalsCPU *kg);
bool use;
/* shading system */

View File

@ -1,10 +1,7 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#ifndef __OSL_SHADER_H__
#define __OSL_SHADER_H__
#ifdef WITH_OSL
#pragma once
/* OSL Shader Engine
*
@ -16,27 +13,12 @@
* This means no thread state must be passed along in the kernel itself.
*/
# include "kernel/types.h"
#include "kernel/osl/types.h"
CCL_NAMESPACE_BEGIN
class Scene;
struct ShaderClosure;
struct ShaderData;
struct IntegratorStateCPU;
struct differential3;
struct KernelGlobalsCPU;
struct OSLGlobals;
struct OSLShadingSystem;
class OSLShader {
public:
/* per thread data */
static void thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals);
static void thread_free(KernelGlobalsCPU *kg);
/* eval */
static void eval_surface(const KernelGlobalsCPU *kg,
const void *state,
@ -54,7 +36,3 @@ class OSLShader {
};
CCL_NAMESPACE_END
#endif
#endif /* __OSL_SHADER_H__ */

View File

@ -20,7 +20,6 @@
#include "kernel/osl/globals.h"
#include "kernel/osl/services.h"
#include "kernel/osl/shader.h"
#include "util/foreach.h"
#include "util/log.h"
@ -30,8 +29,6 @@
#include "kernel/device/cpu/globals.h"
#include "kernel/device/cpu/image.h"
#include "kernel/util/differential.h"
#include "kernel/integrator/state.h"
#include "kernel/integrator/state_flow.h"
@ -123,14 +120,14 @@ ustring OSLRenderServices::u_v("v");
ustring OSLRenderServices::u_empty;
OSLRenderServices::OSLRenderServices(OSL::TextureSystem *texture_system)
: texture_system(texture_system)
: OSL::RendererServices(texture_system)
{
}
OSLRenderServices::~OSLRenderServices()
{
if (texture_system) {
VLOG_INFO << "OSL texture system stats:\n" << texture_system->getstats();
if (m_texturesys) {
VLOG_INFO << "OSL texture system stats:\n" << m_texturesys->getstats();
}
}
@ -1150,7 +1147,7 @@ TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(ustring file
}
/* Get handle from OpenImageIO. */
OSL::TextureSystem *ts = texture_system;
OSL::TextureSystem *ts = m_texturesys;
TextureSystem::TextureHandle *handle = ts->get_texture_handle(filename);
if (handle == NULL) {
return NULL;
@ -1172,7 +1169,7 @@ bool OSLRenderServices::good(TextureSystem::TextureHandle *texture_handle)
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
if (handle->oiio_handle) {
OSL::TextureSystem *ts = texture_system;
OSL::TextureSystem *ts = m_texturesys;
return ts->good(handle->oiio_handle);
}
else {
@ -1294,7 +1291,7 @@ bool OSLRenderServices::texture(ustring filename,
}
case OSLTextureHandle::OIIO: {
/* OpenImageIO texture cache. */
OSL::TextureSystem *ts = texture_system;
OSL::TextureSystem *ts = m_texturesys;
if (handle && handle->oiio_handle) {
if (texture_thread_info == NULL) {
@ -1398,7 +1395,7 @@ bool OSLRenderServices::texture3d(ustring filename,
}
case OSLTextureHandle::OIIO: {
/* OpenImageIO texture cache. */
OSL::TextureSystem *ts = texture_system;
OSL::TextureSystem *ts = m_texturesys;
if (handle && handle->oiio_handle) {
if (texture_thread_info == NULL) {
@ -1482,7 +1479,7 @@ bool OSLRenderServices::environment(ustring filename,
ustring *errormessage)
{
OSLTextureHandle *handle = (OSLTextureHandle *)texture_handle;
OSL::TextureSystem *ts = texture_system;
OSL::TextureSystem *ts = m_texturesys;
bool status = false;
if (handle && handle->oiio_handle) {
@ -1554,7 +1551,7 @@ bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
}
/* Get texture info from OpenImageIO. */
OSL::TextureSystem *ts = texture_system;
OSL::TextureSystem *ts = m_texturesys;
return ts->get_texture_info(filename, subimage, dataname, datatype, data);
}

View File

@ -323,7 +323,6 @@ class OSLRenderServices : public OSL::RendererServices {
* globals to be shared between different render sessions. This saves memory,
* and is required because texture handles are cached as part of the shared
* shading system. */
OSL::TextureSystem *texture_system;
OSLTextureHandleMap textures;
};

View File

@ -1,394 +0,0 @@
/* SPDX-License-Identifier: Apache-2.0
* Copyright 2011-2022 Blender Foundation */
#include <OSL/oslexec.h>
// clang-format off
#include "kernel/device/cpu/compat.h"
#include "kernel/device/cpu/globals.h"
#include "kernel/types.h"
#include "kernel/geom/object.h"
#include "kernel/integrator/state.h"
#include "kernel/osl/globals.h"
#include "kernel/osl/services.h"
#include "kernel/osl/shader.h"
#include "kernel/osl/types.h"
#include "kernel/osl/closures_setup.h"
#include "kernel/util/differential.h"
// clang-format on
#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
/* Threads */
void OSLShader::thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals)
{
/* no osl used? */
if (!osl_globals->use) {
kg->osl = NULL;
return;
}
/* Per thread kernel data init. */
kg->osl = osl_globals;
OSL::ShadingSystem *ss = kg->osl->ss;
OSLThreadData *tdata = new OSLThreadData();
memset((void *)&tdata->globals, 0, sizeof(OSL::ShaderGlobals));
tdata->globals.tracedata = &tdata->tracedata;
tdata->globals.flipHandedness = false;
tdata->osl_thread_info = ss->create_thread_info();
tdata->context = ss->get_context(tdata->osl_thread_info);
tdata->oiio_thread_info = osl_globals->ts->get_perthread_info();
kg->osl_ss = (OSLShadingSystem *)ss;
kg->osl_tdata = tdata;
}
void OSLShader::thread_free(KernelGlobalsCPU *kg)
{
if (!kg->osl)
return;
OSL::ShadingSystem *ss = (OSL::ShadingSystem *)kg->osl_ss;
OSLThreadData *tdata = kg->osl_tdata;
ss->release_context(tdata->context);
ss->destroy_thread_info(tdata->osl_thread_info);
delete tdata;
kg->osl = NULL;
kg->osl_ss = NULL;
kg->osl_tdata = NULL;
}
/* 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->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;
}
}
/* Surface */
static void flatten_surface_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_surface_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_surface_closure_tree(kg, sd, path_flag, add->closureA, weight);
flatten_surface_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;
}
}
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_surface_closure_tree(kg, sd, path_flag, globals->Ci);
}
/* Background */
static void flatten_background_closure_tree(const KernelGlobalsCPU *kg,
ShaderData *sd,
const OSL::ClosureColor *closure,
float3 weight = make_float3(1.0f, 1.0f, 1.0f))
{
/* OSL gives us a closure tree, if we are shading for background there
* is only one supported closure type at the moment, which has no evaluation
* functions, so we just sum the weights */
switch (closure->id) {
case OSL::ClosureColor::MUL: {
OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
flatten_background_closure_tree(kg, sd, mul->closure, weight * TO_FLOAT3(mul->weight));
break;
}
case OSL::ClosureColor::ADD: {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
flatten_background_closure_tree(kg, sd, add->closureA, weight);
flatten_background_closure_tree(kg, sd, 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, 0, weight, reinterpret_cast<const Upper##Closure *>(comp + 1)); \
break; \
}
#include "closures_template.h"
default:
break;
}
}
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_background_closure_tree(kg, sd, globals->Ci);
}
/* Volume */
static void flatten_volume_closure_tree(const KernelGlobalsCPU *kg,
ShaderData *sd,
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_volume_closure_tree(kg, sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
break;
}
case OSL::ClosureColor::ADD: {
OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
flatten_volume_closure_tree(kg, sd, add->closureA, weight);
flatten_volume_closure_tree(kg, sd, 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, 0, weight, reinterpret_cast<const Upper##Closure *>(comp + 1)); \
break; \
}
#include "closures_template.h"
default:
break;
}
}
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_volume_closure_tree(kg, sd, 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

View File

@ -17,7 +17,6 @@
# include "kernel/osl/globals.h"
# include "kernel/osl/services.h"
# include "kernel/osl/shader.h"
# include "util/aligned_malloc.h"
# include "util/foreach.h"