Cycles: Support building with latest OSL-1.7dev
authorSergey Sharybin <sergey.vfx@gmail.com>
Wed, 23 Sep 2015 07:23:37 +0000 (12:23 +0500)
committerSergey Sharybin <sergey.vfx@gmail.com>
Wed, 23 Sep 2015 07:27:02 +0000 (12:27 +0500)
So now the following OSL versions are supported (at least for compilation):

- 1.5 with closure alignment patch applied
- 1.6.8 release
- 1.7 development version from latest git

intern/cycles/kernel/osl/background.cpp
intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp
intern/cycles/kernel/osl/bsdf_phong_ramp.cpp
intern/cycles/kernel/osl/emissive.cpp
intern/cycles/kernel/osl/osl_bssrdf.cpp
intern/cycles/kernel/osl/osl_closures.h
intern/cycles/kernel/osl/osl_shader.cpp

index 2facced09146cb98a2eb0fe305e0e5dbe59d4496..4d70bc80006335112350391c2108becaedcc3c4e 100644 (file)
@@ -77,7 +77,7 @@ public:
 ClosureParam *closure_background_params()
 {
        static ClosureParam params[] = {
-           CLOSURE_STRING_KEYPARAM("label"),
+           CLOSURE_STRING_KEYPARAM(GenericBackgroundClosure, label, "label"),
            CLOSURE_FINISH_PARAM(GenericBackgroundClosure)
        };
        return params;
@@ -98,7 +98,7 @@ CCLOSURE_PREPARE(closure_holdout_prepare, HoldoutClosure)
 ClosureParam *closure_ambient_occlusion_params()
 {
        static ClosureParam params[] = {
-           CLOSURE_STRING_KEYPARAM("label"),
+           CLOSURE_STRING_KEYPARAM(AmbientOcclusionClosure, label, "label"),
            CLOSURE_FINISH_PARAM(AmbientOcclusionClosure)
        };
        return params;
index 43929fbe928b0c4888b099821b9f14086a49912a..b3c71e4a706a80c6b9aad97be82677696e212aca 100644 (file)
@@ -93,7 +93,7 @@ ClosureParam *closure_bsdf_diffuse_ramp_params()
        static ClosureParam params[] = {
                CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, sc.N),
                CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8),
-               CLOSURE_STRING_KEYPARAM("label"),
+               CLOSURE_STRING_KEYPARAM(DiffuseRampClosure, label, "label"),
            CLOSURE_FINISH_PARAM(DiffuseRampClosure)
        };
        return params;
index 497c4f0dc5cab042f85f187b1ad39a950f1e6b39..99f510d31ed50a772e78bbe1c3fe486db291a4d6 100644 (file)
@@ -93,7 +93,7 @@ ClosureParam *closure_bsdf_phong_ramp_params()
                CLOSURE_FLOAT3_PARAM(PhongRampClosure, sc.N),
                CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0),
                CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8),
-               CLOSURE_STRING_KEYPARAM("label"),
+               CLOSURE_STRING_KEYPARAM(PhongRampClosure, label, "label"),
            CLOSURE_FINISH_PARAM(PhongRampClosure)
        };
        return params;
index 02935542c5650ca24e6ab56fa438e204cc3ce7fe..9a95fa57a8113882d72368d2e12046f254f8134c 100644 (file)
@@ -77,7 +77,7 @@ public:
 ClosureParam *closure_emission_params()
 {
        static ClosureParam params[] = {
-           CLOSURE_STRING_KEYPARAM("label"),
+           CLOSURE_STRING_KEYPARAM(GenericEmissiveClosure, label, "label"),
            CLOSURE_FINISH_PARAM(GenericEmissiveClosure)
        };
        return params;
index 88998037751b12a7813c48242a023f1c9972d4ed..bc395922077d0ae98cb7341e84b1d550dcc6c96d 100644 (file)
@@ -69,7 +69,7 @@ ClosureParam *closure_bssrdf_cubic_params()
                CLOSURE_FLOAT3_PARAM(CubicBSSRDFClosure, radius),
                CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.data1),
                CLOSURE_FLOAT_PARAM(CubicBSSRDFClosure, sc.T.x),
-           CLOSURE_STRING_KEYPARAM("label"),
+           CLOSURE_STRING_KEYPARAM(CubicBSSRDFClosure, label, "label"),
            CLOSURE_FINISH_PARAM(CubicBSSRDFClosure)
        };
        return params;
@@ -97,7 +97,7 @@ ClosureParam *closure_bssrdf_gaussian_params()
                CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, sc.N),
                CLOSURE_FLOAT3_PARAM(GaussianBSSRDFClosure, radius),
                CLOSURE_FLOAT_PARAM(GaussianBSSRDFClosure, sc.data1),
-           CLOSURE_STRING_KEYPARAM("label"),
+           CLOSURE_STRING_KEYPARAM(GaussianBSSRDFClosure, label, "label"),
            CLOSURE_FINISH_PARAM(GaussianBSSRDFClosure)
        };
        return params;
index ef67ef52fc0a5a923ddfa33e163507549aae75fa..97bd1b1ac928bf74e29837651a33b491236becc2 100644 (file)
@@ -78,6 +78,11 @@ void name(RendererServices *, int id, void *data) \
 #define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z)
 #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2])
 
+#if OSL_LIBRARY_VERSION_CODE < 10700
+#  undef CLOSURE_STRING_KEYPARAM
+#  define CLOSURE_STRING_KEYPARAM(st, fld, key) { TypeDesc::TypeString, 0, key, 0 }
+#endif
+
 /* Closure */
 
 class CClosurePrimitive {
@@ -97,6 +102,10 @@ public:
        virtual void setup() {}
 
        Category category;
+
+#if OSL_LIBRARY_VERSION_CODE >= 10700
+       OSL::ustring label;
+#endif
 };
 
 /* BSDF */
@@ -175,7 +184,7 @@ static ClosureParam *bsdf_##lower##_params() \
 /* parameters */
 
 #define BSDF_CLOSURE_CLASS_END(Upper, lower) \
-               CLOSURE_STRING_KEYPARAM("label"), \
+               CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), \
            CLOSURE_FINISH_PARAM(Upper##Closure) \
        }; \
        return params; \
@@ -223,7 +232,7 @@ static ClosureParam *volume_##lower##_params() \
 /* parameters */
 
 #define VOLUME_CLOSURE_CLASS_END(Upper, lower) \
-               CLOSURE_STRING_KEYPARAM("label"), \
+               CLOSURE_STRING_KEYPARAM(Upper##Closure, label, "label"), \
            CLOSURE_FINISH_PARAM(Upper##Closure) \
        }; \
        return params; \
index 8cfe0cbcbd47bc45cd0d1fa753820da33c411c56..2f234aa25eadb8805ad95a9dab59228233e08f2a 100644 (file)
@@ -146,165 +146,175 @@ static void flatten_surface_closure_tree(ShaderData *sd, int path_flag,
        /* OSL gives us a closure tree, we flatten it into arrays per
         * closure type, for evaluation, sampling, etc later on. */
 
-       if(closure->type == OSL::ClosureColor::COMPONENT) {
-               OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
-               CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+#if OSL_LIBRARY_VERSION_CODE < 10700
+       switch(closure->type) {
+#else
+       switch(closure->id) {
+#endif
+               case OSL::ClosureColor::MUL: {
+                       OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+                       flatten_surface_closure_tree(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(sd, path_flag, add->closureA, weight);
+                       flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
+                       break;
+               }
+               default: {
+                       OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+                       CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
 
-               if(prim) {
-                       ShaderClosure sc;
+                       if(prim) {
+                               ShaderClosure sc;
 
 #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
-                       weight = weight*TO_FLOAT3(comp->w);
+                               weight = weight*TO_FLOAT3(comp->w);
 #endif
-                       sc.weight = weight;
+                               sc.weight = weight;
 
-                       prim->setup();
+                               prim->setup();
 
-                       switch (prim->category) {
-                               case CClosurePrimitive::BSDF: {
-                                       CBSDFClosure *bsdf = (CBSDFClosure *)prim;
-                                       int scattering = bsdf->scattering();
+                               switch(prim->category) {
+                                       case CClosurePrimitive::BSDF: {
+                                               CBSDFClosure *bsdf = (CBSDFClosure *)prim;
+                                               int scattering = bsdf->scattering();
 
-                                       /* caustic options */
-                                       if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
-                                               KernelGlobals *kg = sd->osl_globals;
+                                               /* caustic options */
+                                               if((scattering & LABEL_GLOSSY) && (path_flag & PATH_RAY_DIFFUSE)) {
+                                                       KernelGlobals *kg = sd->osl_globals;
 
-                                               if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
-                                                  (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT))) {
-                                                       return;
+                                                       if((!kernel_data.integrator.caustics_reflective && (scattering & LABEL_REFLECT)) ||
+                                                          (!kernel_data.integrator.caustics_refractive && (scattering & LABEL_TRANSMIT)))
+                                                       {
+                                                               return;
+                                                       }
                                                }
-                                       }
 
-                                       /* sample weight */
-                                       float sample_weight = fabsf(average(weight));
+                                               /* sample weight */
+                                               float sample_weight = fabsf(average(weight));
 
-                                       sc.sample_weight = sample_weight;
+                                               sc.sample_weight = sample_weight;
 
-                                       sc.type = bsdf->sc.type;
-                                       sc.N = bsdf->sc.N;
-                                       sc.T = bsdf->sc.T;
-                                       sc.data0 = bsdf->sc.data0;
-                                       sc.data1 = bsdf->sc.data1;
-                                       sc.data2 = bsdf->sc.data2;
-                                       sc.prim = bsdf->sc.prim;
+                                               sc.type = bsdf->sc.type;
+                                               sc.N = bsdf->sc.N;
+                                               sc.T = bsdf->sc.T;
+                                               sc.data0 = bsdf->sc.data0;
+                                               sc.data1 = bsdf->sc.data1;
+                                               sc.data2 = bsdf->sc.data2;
+                                               sc.prim = bsdf->sc.prim;
 
-                                       /* add */
-                                       if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
-                                               sd->closure[sd->num_closure++] = sc;
-                                               sd->flag |= bsdf->shaderdata_flag();
-                                       }
-                                       break;
-                               }
-                               case CClosurePrimitive::Emissive: {
-                                       /* sample weight */
-                                       float sample_weight = fabsf(average(weight));
-
-                                       sc.sample_weight = sample_weight;
-                                       sc.type = CLOSURE_EMISSION_ID;
-                                       sc.data0 = 0.0f;
-                                       sc.data1 = 0.0f;
-                                       sc.data2 = 0.0f;
-                                       sc.prim = NULL;
-
-                                       /* flag */
-                                       if(sd->num_closure < MAX_CLOSURE) {
-                                               sd->closure[sd->num_closure++] = sc;
-                                               sd->flag |= SD_EMISSION;
-                                       }
-                                       break;
-                               }
-                               case CClosurePrimitive::AmbientOcclusion: {
-                                       /* sample weight */
-                                       float sample_weight = fabsf(average(weight));
-
-                                       sc.sample_weight = sample_weight;
-                                       sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
-                                       sc.data0 = 0.0f;
-                                       sc.data1 = 0.0f;
-                                       sc.data2 = 0.0f;
-                                       sc.prim = NULL;
-
-                                       if(sd->num_closure < MAX_CLOSURE) {
-                                               sd->closure[sd->num_closure++] = sc;
-                                               sd->flag |= SD_AO;
-                                       }
-                                       break;
-                               }
-                               case CClosurePrimitive::Holdout: {
-                                       sc.sample_weight = 0.0f;
-                                       sc.type = CLOSURE_HOLDOUT_ID;
-                                       sc.data0 = 0.0f;
-                                       sc.data1 = 0.0f;
-                                       sc.data2 = 0.0f;
-                                       sc.prim = NULL;
-
-                                       if(sd->num_closure < MAX_CLOSURE) {
-                                               sd->closure[sd->num_closure++] = sc;
-                                               sd->flag |= SD_HOLDOUT;
+                                               /* add */
+                                               if(sc.sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure < MAX_CLOSURE) {
+                                                       sd->closure[sd->num_closure++] = sc;
+                                                       sd->flag |= bsdf->shaderdata_flag();
+                                               }
+                                               break;
                                        }
-                                       break;
-                               }
-                               case CClosurePrimitive::BSSRDF: {
-                                       CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
-                                       float sample_weight = fabsf(average(weight));
+                                       case CClosurePrimitive::Emissive: {
+                                               /* sample weight */
+                                               float sample_weight = fabsf(average(weight));
 
-                                       if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
                                                sc.sample_weight = sample_weight;
-
-                                               sc.type = bssrdf->sc.type;
-                                               sc.N = bssrdf->sc.N;
-                                               sc.data1 = bssrdf->sc.data1;
-                                               sc.T.x = bssrdf->sc.T.x;
+                                               sc.type = CLOSURE_EMISSION_ID;
+                                               sc.data0 = 0.0f;
+                                               sc.data1 = 0.0f;
+                                               sc.data2 = 0.0f;
                                                sc.prim = NULL;
 
-                                               /* disable in case of diffuse ancestor, can't see it well then and
-                                                * adds considerably noise due to probabilities of continuing path
-                                                * getting lower and lower */
-                                               if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
-                                                       bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
-
-                                               /* create one closure for each color channel */
-                                               if(fabsf(weight.x) > 0.0f) {
-                                                       sc.weight = make_float3(weight.x, 0.0f, 0.0f);
-                                                       sc.data0 = bssrdf->radius.x;
-                                                       sc.data1 = 0.0f;
-                                                       sd->flag |= bssrdf_setup(&sc, sc.type);
+                                               /* flag */
+                                               if(sd->num_closure < MAX_CLOSURE) {
                                                        sd->closure[sd->num_closure++] = sc;
+                                                       sd->flag |= SD_EMISSION;
                                                }
+                                               break;
+                                       }
+                                       case CClosurePrimitive::AmbientOcclusion: {
+                                               /* sample weight */
+                                               float sample_weight = fabsf(average(weight));
 
-                                               if(fabsf(weight.y) > 0.0f) {
-                                                       sc.weight = make_float3(0.0f, weight.y, 0.0f);
-                                                       sc.data0 = bssrdf->radius.y;
-                                                       sc.data1 = 0.0f;
-                                                       sd->flag |= bssrdf_setup(&sc, sc.type);
+                                               sc.sample_weight = sample_weight;
+                                               sc.type = CLOSURE_AMBIENT_OCCLUSION_ID;
+                                               sc.data0 = 0.0f;
+                                               sc.data1 = 0.0f;
+                                               sc.data2 = 0.0f;
+                                               sc.prim = NULL;
+
+                                               if(sd->num_closure < MAX_CLOSURE) {
                                                        sd->closure[sd->num_closure++] = sc;
+                                                       sd->flag |= SD_AO;
                                                }
+                                               break;
+                                       }
+                                       case CClosurePrimitive::Holdout: {
+                                               sc.sample_weight = 0.0f;
+                                               sc.type = CLOSURE_HOLDOUT_ID;
+                                               sc.data0 = 0.0f;
+                                               sc.data1 = 0.0f;
+                                               sc.data2 = 0.0f;
+                                               sc.prim = NULL;
 
-                                               if(fabsf(weight.z) > 0.0f) {
-                                                       sc.weight = make_float3(0.0f, 0.0f, weight.z);
-                                                       sc.data0 = bssrdf->radius.z;
-                                                       sc.data1 = 0.0f;
-                                                       sd->flag |= bssrdf_setup(&sc, sc.type);
+                                               if(sd->num_closure < MAX_CLOSURE) {
                                                        sd->closure[sd->num_closure++] = sc;
+                                                       sd->flag |= SD_HOLDOUT;
+                                               }
+                                               break;
+                                       }
+                                       case CClosurePrimitive::BSSRDF: {
+                                               CBSSRDFClosure *bssrdf = (CBSSRDFClosure *)prim;
+                                               float sample_weight = fabsf(average(weight));
+
+                                               if(sample_weight > CLOSURE_WEIGHT_CUTOFF && sd->num_closure+2 < MAX_CLOSURE) {
+                                                       sc.sample_weight = sample_weight;
+
+                                                       sc.type = bssrdf->sc.type;
+                                                       sc.N = bssrdf->sc.N;
+                                                       sc.data1 = bssrdf->sc.data1;
+                                                       sc.T.x = bssrdf->sc.T.x;
+                                                       sc.prim = NULL;
+
+                                                       /* disable in case of diffuse ancestor, can't see it well then and
+                                                        * adds considerably noise due to probabilities of continuing path
+                                                        * getting lower and lower */
+                                                       if(path_flag & PATH_RAY_DIFFUSE_ANCESTOR)
+                                                               bssrdf->radius = make_float3(0.0f, 0.0f, 0.0f);
+
+                                                       /* create one closure for each color channel */
+                                                       if(fabsf(weight.x) > 0.0f) {
+                                                               sc.weight = make_float3(weight.x, 0.0f, 0.0f);
+                                                               sc.data0 = bssrdf->radius.x;
+                                                               sc.data1 = 0.0f;
+                                                               sd->flag |= bssrdf_setup(&sc, sc.type);
+                                                               sd->closure[sd->num_closure++] = sc;
+                                                       }
+
+                                                       if(fabsf(weight.y) > 0.0f) {
+                                                               sc.weight = make_float3(0.0f, weight.y, 0.0f);
+                                                               sc.data0 = bssrdf->radius.y;
+                                                               sc.data1 = 0.0f;
+                                                               sd->flag |= bssrdf_setup(&sc, sc.type);
+                                                               sd->closure[sd->num_closure++] = sc;
+                                                       }
+
+                                                       if(fabsf(weight.z) > 0.0f) {
+                                                               sc.weight = make_float3(0.0f, 0.0f, weight.z);
+                                                               sc.data0 = bssrdf->radius.z;
+                                                               sc.data1 = 0.0f;
+                                                               sd->flag |= bssrdf_setup(&sc, sc.type);
+                                                               sd->closure[sd->num_closure++] = sc;
+                                                       }
                                                }
+                                               break;
                                        }
-                                       break;
+                                       case CClosurePrimitive::Background:
+                                       case CClosurePrimitive::Volume:
+                                               break; /* not relevant */
                                }
-                               case CClosurePrimitive::Background:
-                               case CClosurePrimitive::Volume:
-                                       break; /* not relevant */
                        }
+                       break;
                }
        }
-       else if(closure->type == OSL::ClosureColor::MUL) {
-               OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
-               flatten_surface_closure_tree(sd, path_flag, mul->closure, TO_FLOAT3(mul->weight) * weight);
-       }
-       else if(closure->type == OSL::ClosureColor::ADD) {
-               OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
-               flatten_surface_closure_tree(sd, path_flag, add->closureA, weight);
-               flatten_surface_closure_tree(sd, path_flag, add->closureB, weight);
-       }
 }
 
 void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)
@@ -335,27 +345,33 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure)
         * is only one supported closure type at the moment, which has no evaluation
         * functions, so we just sum the weights */
 
-       if(closure->type == OSL::ClosureColor::COMPONENT) {
-               OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
-               CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
-
-               if(prim && prim->category == CClosurePrimitive::Background)
-#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
-                       return TO_FLOAT3(comp->w);
+#if OSL_LIBRARY_VERSION_CODE < 10700
+       switch(closure->type) {
 #else
-                       return make_float3(1.0f, 1.0f, 1.0f);
+       switch(closure->id) {
 #endif
-       }
-       else if(closure->type == OSL::ClosureColor::MUL) {
-               OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+               case OSL::ClosureColor::MUL: {
+                       OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
 
-               return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
-       }
-       else if(closure->type == OSL::ClosureColor::ADD) {
-               OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+                       return TO_FLOAT3(mul->weight) * flatten_background_closure_tree(mul->closure);
+               }
+               case OSL::ClosureColor::ADD: {
+                       OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
 
-               return flatten_background_closure_tree(add->closureA) +
-                      flatten_background_closure_tree(add->closureB);
+                       return flatten_background_closure_tree(add->closureA) +
+                              flatten_background_closure_tree(add->closureB);
+               }
+               default: {
+                       OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+                       CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+
+                       if(prim && prim->category == CClosurePrimitive::Background)
+#ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
+                               return TO_FLOAT3(comp->w);
+#else
+                               return make_float3(1.0f, 1.0f, 1.0f);
+#endif
+               }
        }
 
        return make_float3(0.0f, 0.0f, 0.0f);
@@ -390,76 +406,84 @@ static void flatten_volume_closure_tree(ShaderData *sd,
        /* OSL gives us a closure tree, we flatten it into arrays per
         * closure type, for evaluation, sampling, etc later on. */
 
-       if(closure->type == OSL::ClosureColor::COMPONENT) {
-               OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
-               CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
+#if OSL_LIBRARY_VERSION_CODE < 10700
+       switch(closure->type) {
+#else
+       switch(closure->id) {
+#endif
+               case OSL::ClosureColor::MUL: {
+                       OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
+                       flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
+                       break;
+               }
+               case OSL::ClosureColor::ADD: {
+                       OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
+                       flatten_volume_closure_tree(sd, add->closureA, weight);
+                       flatten_volume_closure_tree(sd, add->closureB, weight);
+                       break;
+               }
+               default: {
+                       OSL::ClosureComponent *comp = (OSL::ClosureComponent *)closure;
+                       CClosurePrimitive *prim = (CClosurePrimitive *)comp->data();
 
-               if(prim) {
-                       ShaderClosure sc;
+                       if(prim) {
+                               ShaderClosure sc;
 
 #ifdef OSL_SUPPORTS_WEIGHTED_CLOSURE_COMPONENTS
-                       weight = weight*TO_FLOAT3(comp->w);
+                               weight = weight*TO_FLOAT3(comp->w);
 #endif
-                       sc.weight = weight;
-
-                       prim->setup();
-
-                       switch (prim->category) {
-                               case CClosurePrimitive::Volume: {
-                                       CVolumeClosure *volume = (CVolumeClosure *)prim;
-                                       /* sample weight */
-                                       float sample_weight = fabsf(average(weight));
-
-                                       sc.sample_weight = sample_weight;
-                                       sc.type = volume->sc.type;
-                                       sc.data0 = volume->sc.data0;
-                                       sc.data1 = volume->sc.data1;
-
-                                       /* add */
-                                       if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) &&
-                                          (sd->num_closure < MAX_CLOSURE))
-                                       {
-                                               sd->closure[sd->num_closure++] = sc;
-                                               sd->flag |= volume->shaderdata_flag();
+                               sc.weight = weight;
+
+                               prim->setup();
+
+                               switch(prim->category) {
+                                       case CClosurePrimitive::Volume: {
+                                               CVolumeClosure *volume = (CVolumeClosure *)prim;
+                                               /* sample weight */
+                                               float sample_weight = fabsf(average(weight));
+
+                                               sc.sample_weight = sample_weight;
+                                               sc.type = volume->sc.type;
+                                               sc.data0 = volume->sc.data0;
+                                               sc.data1 = volume->sc.data1;
+
+                                               /* add */
+                                               if((sc.sample_weight > CLOSURE_WEIGHT_CUTOFF) &&
+                                                  (sd->num_closure < MAX_CLOSURE))
+                                               {
+                                                       sd->closure[sd->num_closure++] = sc;
+                                                       sd->flag |= volume->shaderdata_flag();
+                                               }
+                                               break;
                                        }
-                                       break;
-                               }
-                               case CClosurePrimitive::Emissive: {
-                                       /* sample weight */
-                                       float sample_weight = fabsf(average(weight));
-
-                                       sc.sample_weight = sample_weight;
-                                       sc.type = CLOSURE_EMISSION_ID;
-                                       sc.data0 = 0.0f;
-                                       sc.data1 = 0.0f;
-                                       sc.prim = NULL;
-
-                                       /* flag */
-                                       if(sd->num_closure < MAX_CLOSURE) {
-                                               sd->closure[sd->num_closure++] = sc;
-                                               sd->flag |= SD_EMISSION;
+                                       case CClosurePrimitive::Emissive: {
+                                               /* sample weight */
+                                               float sample_weight = fabsf(average(weight));
+
+                                               sc.sample_weight = sample_weight;
+                                               sc.type = CLOSURE_EMISSION_ID;
+                                               sc.data0 = 0.0f;
+                                               sc.data1 = 0.0f;
+                                               sc.prim = NULL;
+
+                                               /* flag */
+                                               if(sd->num_closure < MAX_CLOSURE) {
+                                                       sd->closure[sd->num_closure++] = sc;
+                                                       sd->flag |= SD_EMISSION;
+                                               }
+                                               break;
                                        }
-                                       break;
+                                       case CClosurePrimitive::Holdout:
+                                               break; /* not implemented */
+                                       case CClosurePrimitive::Background:
+                                       case CClosurePrimitive::BSDF:
+                                       case CClosurePrimitive::BSSRDF:
+                                       case CClosurePrimitive::AmbientOcclusion:
+                                               break; /* not relevant */
                                }
-                               case CClosurePrimitive::Holdout:
-                                       break; /* not implemented */
-                               case CClosurePrimitive::Background:
-                               case CClosurePrimitive::BSDF:
-                               case CClosurePrimitive::BSSRDF:
-                               case CClosurePrimitive::AmbientOcclusion:
-                                       break; /* not relevant */
                        }
                }
        }
-       else if(closure->type == OSL::ClosureColor::MUL) {
-               OSL::ClosureMul *mul = (OSL::ClosureMul *)closure;
-               flatten_volume_closure_tree(sd, mul->closure, TO_FLOAT3(mul->weight) * weight);
-       }
-       else if(closure->type == OSL::ClosureColor::ADD) {
-               OSL::ClosureAdd *add = (OSL::ClosureAdd *)closure;
-               flatten_volume_closure_tree(sd, add->closureA, weight);
-               flatten_volume_closure_tree(sd, add->closureB, weight);
-       }
 }
 
 void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx)