diff options
author | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-12-15 14:18:42 +0400 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@pandora.be> | 2012-12-15 14:18:42 +0400 |
commit | 06888b7bebf66c5b05dd1a8106e35c57458252c0 (patch) | |
tree | ab9a5c6412438c8988a4e8116432ecd3b5705df3 | |
parent | 35dd893c368548b5d9d7bb56a1b9db07c71165d2 (diff) |
Cycles OSL minor optimizations: recycle shading context, don't do memory
allocations for trace data, avoid some virtual function calls. Only helps
a few percentages.
21 files changed, 596 insertions, 687 deletions
diff --git a/intern/cycles/kernel/CMakeLists.txt b/intern/cycles/kernel/CMakeLists.txt index b7878e9b00f..b6e024dde17 100644 --- a/intern/cycles/kernel/CMakeLists.txt +++ b/intern/cycles/kernel/CMakeLists.txt @@ -56,6 +56,7 @@ set(SRC_CLOSURE_HEADERS closure/bsdf_reflection.h closure/bsdf_refraction.h closure/bsdf_transparent.h + closure/bsdf_util.h closure/bsdf_ward.h closure/bsdf_westin.h closure/emissive.h @@ -64,7 +65,6 @@ set(SRC_CLOSURE_HEADERS set(SRC_SVM_HEADERS svm/svm.h svm/svm_attribute.h - svm/svm_bsdf.h svm/svm_camera.h svm/svm_closure.h svm/svm_convert.h diff --git a/intern/cycles/kernel/closure/bsdf.h b/intern/cycles/kernel/closure/bsdf.h index cfb6321a918..f26aefe7fd3 100644 --- a/intern/cycles/kernel/closure/bsdf.h +++ b/intern/cycles/kernel/closure/bsdf.h @@ -1,137 +1,296 @@ /* - * Adapted from Open Shading Language with this license: + * Copyright 2011, Blender Foundation. * - * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. - * All Rights Reserved. + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. * - * Modifications Copyright 2011, Blender Foundation. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Sony Pictures Imageworks nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __OSL_BSDF_H__ -#define __OSL_BSDF_H__ +#include "../closure/bsdf_ashikhmin_velvet.h" +#include "../closure/bsdf_diffuse.h" +#include "../closure/bsdf_oren_nayar.h" +#include "../closure/bsdf_phong_ramp.h" +#include "../closure/bsdf_diffuse_ramp.h" +#include "../closure/bsdf_microfacet.h" +#include "../closure/bsdf_reflection.h" +#include "../closure/bsdf_refraction.h" +#include "../closure/bsdf_transparent.h" +#ifdef __ANISOTROPIC__ +#include "../closure/bsdf_ward.h" +#endif +#include "../closure/bsdf_westin.h" CCL_NAMESPACE_BEGIN -__device float fresnel_dielectric(float eta, const float3 N, - const float3 I, float3 *R, float3 *T, -#ifdef __RAY_DIFFERENTIALS__ - const float3 dIdx, const float3 dIdy, - float3 *dRdx, float3 *dRdy, - float3 *dTdx, float3 *dTdy, -#endif - bool *is_inside) +__device int bsdf_sample(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf) { - float cos = dot(N, I), neta; - float3 Nn; - // compute reflection - *R = (2 * cos)* N - I; -#ifdef __RAY_DIFFERENTIALS__ - *dRdx = (2 * dot(N, dIdx)) * N - dIdx; - *dRdy = (2 * dot(N, dIdy)) * N - dIdy; + int label; + +#ifdef __OSL__ + if(kg->osl && sc->prim) + return OSLShader::bsdf_sample(sd, sc, randu, randv, *eval, *omega_in, *domega_in, *pdf); #endif - // check which side of the surface we are on - if(cos > 0) { - // we are on the outside of the surface, going in - neta = 1 / eta; - Nn = N; - *is_inside = false; - } - else { - // we are inside the surface, - cos = -cos; - neta = eta; - Nn = -N; - *is_inside = true; - } - *R = (2 * cos)* Nn - I; - float arg = 1 -(neta * neta *(1 -(cos * cos))); - if(arg < 0) { - *T = make_float3(0.0f, 0.0f, 0.0f); -#ifdef __RAY_DIFFERENTIALS__ - *dTdx = make_float3(0.0f, 0.0f, 0.0f); - *dTdy = make_float3(0.0f, 0.0f, 0.0f); + + switch(sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; +#ifdef __SVM__ + case CLOSURE_BSDF_OREN_NAYAR_ID: + label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_DIFFUSE_RAMP_ID: + label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break;*/ + case CLOSURE_BSDF_TRANSLUCENT_ID: + label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_REFLECTION_ID: + label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_REFRACTION_ID: + label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_TRANSPARENT_ID: + label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + label = bsdf_microfacet_ggx_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: + label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; +#ifdef __ANISOTROPIC__ + case CLOSURE_BSDF_WARD_ID: + label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; #endif - return 1; // total internal reflection - } - else { - float dnp = sqrtf(arg); - float nK = (neta * cos)- dnp; - *T = -(neta * I)+(nK * Nn); -#ifdef __RAY_DIFFERENTIALS__ - *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn; - *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn; + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: + label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; + case CLOSURE_BSDF_WESTIN_SHEEN_ID: + label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, + eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); + break; #endif - // compute Fresnel terms - float cosTheta1 = cos; // N.R - float cosTheta2 = -dot(Nn, *T); - float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2); - float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2); - return 0.5f * (pPara * pPara + pPerp * pPerp); + default: + label = LABEL_NONE; + break; } + + return label; } -__device float fresnel_dielectric_cos(float cosi, float eta) +__device float3 bsdf_eval(KernelGlobals *kg, const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf) { - // compute fresnel reflectance without explicitly computing - // the refracted direction - float c = fabsf(cosi); - float g = eta * eta - 1 + c * c; - if(g > 0) { - g = sqrtf(g); - float A = (g - c)/(g + c); - float B = (c *(g + c)- 1)/(c *(g - c)+ 1); - return 0.5f * A * A *(1 + B * B); + float3 eval; + +#ifdef __OSL__ + if(kg->osl && sc->prim) + return OSLShader::bsdf_eval(sd, sc, omega_in, *pdf); +#endif + + if(dot(sd->Ng, omega_in) >= 0.0f) { + switch(sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); + break; +#ifdef __SVM__ + case CLOSURE_BSDF_OREN_NAYAR_ID: + eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); + break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_DIFFUSE_RAMP_ID: + eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf); + break;*/ + case CLOSURE_BSDF_TRANSLUCENT_ID: + eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_REFLECTION_ID: + eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_REFRACTION_ID: + eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_TRANSPARENT_ID: + eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: + eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); + break; +#ifdef __ANISOTROPIC__ + case CLOSURE_BSDF_WARD_ID: + eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); + break; +#endif + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: + eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_WESTIN_SHEEN_ID: + eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf); + break; +#endif + default: + eval = make_float3(0.0f, 0.0f, 0.0f); + break; + } + } + else { + switch(sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); + break; +#ifdef __SVM__ + case CLOSURE_BSDF_OREN_NAYAR_ID: + eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_TRANSLUCENT_ID: + eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_REFLECTION_ID: + eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_REFRACTION_ID: + eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_TRANSPARENT_ID: + eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: + eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); + break; +#ifdef __ANISOTROPIC__ + case CLOSURE_BSDF_WARD_ID: + eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); + break; +#endif + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: + eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf); + break; + case CLOSURE_BSDF_WESTIN_SHEEN_ID: + eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf); + break; +#endif + default: + eval = make_float3(0.0f, 0.0f, 0.0f); + break; + } } - return 1.0f; // TIR(no refracted component) -} -__device float fresnel_conductor(float cosi, float eta, float k) -{ - float tmp_f = eta * eta + k * k; - float tmp = tmp_f * cosi * cosi; - float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/ - (tmp + (2.0f * eta * cosi) + 1); - float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/ - (tmp_f + (2.0f * eta * cosi) + cosi * cosi); - return(Rparl2 + Rperp2) * 0.5f; + return eval; } -__device float smooth_step(float edge0, float edge1, float x) +__device void bsdf_blur(KernelGlobals *kg, ShaderClosure *sc, float roughness) { - float result; - if(x < edge0) result = 0.0f; - else if(x >= edge1) result = 1.0f; - else { - float t = (x - edge0)/(edge1 - edge0); - result = (3.0f-2.0f*t)*(t*t); +#ifdef __OSL__ + if(kg->osl && sc->prim) { + OSLShader::bsdf_blur(sc, roughness); + return; + } +#endif + + switch(sc->type) { + case CLOSURE_BSDF_DIFFUSE_ID: + bsdf_diffuse_blur(sc, roughness); + break; +#ifdef __SVM__ + case CLOSURE_BSDF_OREN_NAYAR_ID: + bsdf_oren_nayar_blur(sc, roughness); + break; + /*case CLOSURE_BSDF_PHONG_RAMP_ID: + bsdf_phong_ramp_blur(sc, roughness); + break; + case CLOSURE_BSDF_DIFFUSE_RAMP_ID: + bsdf_diffuse_ramp_blur(sc, roughness); + break;*/ + case CLOSURE_BSDF_TRANSLUCENT_ID: + bsdf_translucent_blur(sc, roughness); + break; + case CLOSURE_BSDF_REFLECTION_ID: + bsdf_reflection_blur(sc, roughness); + break; + case CLOSURE_BSDF_REFRACTION_ID: + bsdf_refraction_blur(sc, roughness); + break; + case CLOSURE_BSDF_TRANSPARENT_ID: + bsdf_transparent_blur(sc, roughness); + break; + case CLOSURE_BSDF_MICROFACET_GGX_ID: + case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: + bsdf_microfacet_ggx_blur(sc, roughness); + break; + case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: + case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: + bsdf_microfacet_beckmann_blur(sc, roughness); + break; +#ifdef __ANISOTROPIC__ + case CLOSURE_BSDF_WARD_ID: + bsdf_ward_blur(sc, roughness); + break; +#endif + case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: + bsdf_ashikhmin_velvet_blur(sc, roughness); + break; + case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: + bsdf_westin_backscatter_blur(sc, roughness); + break; + case CLOSURE_BSDF_WESTIN_SHEEN_ID: + bsdf_westin_sheen_blur(sc, roughness); + break; +#endif + default: + break; } - return result; } CCL_NAMESPACE_END -#endif /* __OSL_BSDF_H__ */ - diff --git a/intern/cycles/kernel/closure/bsdf_util.h b/intern/cycles/kernel/closure/bsdf_util.h new file mode 100644 index 00000000000..cfb6321a918 --- /dev/null +++ b/intern/cycles/kernel/closure/bsdf_util.h @@ -0,0 +1,137 @@ +/* + * Adapted from Open Shading Language with this license: + * + * Copyright (c) 2009-2010 Sony Pictures Imageworks Inc., et al. + * All Rights Reserved. + * + * Modifications Copyright 2011, Blender Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Sony Pictures Imageworks nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __OSL_BSDF_H__ +#define __OSL_BSDF_H__ + +CCL_NAMESPACE_BEGIN + +__device float fresnel_dielectric(float eta, const float3 N, + const float3 I, float3 *R, float3 *T, +#ifdef __RAY_DIFFERENTIALS__ + const float3 dIdx, const float3 dIdy, + float3 *dRdx, float3 *dRdy, + float3 *dTdx, float3 *dTdy, +#endif + bool *is_inside) +{ + float cos = dot(N, I), neta; + float3 Nn; + // compute reflection + *R = (2 * cos)* N - I; +#ifdef __RAY_DIFFERENTIALS__ + *dRdx = (2 * dot(N, dIdx)) * N - dIdx; + *dRdy = (2 * dot(N, dIdy)) * N - dIdy; +#endif + // check which side of the surface we are on + if(cos > 0) { + // we are on the outside of the surface, going in + neta = 1 / eta; + Nn = N; + *is_inside = false; + } + else { + // we are inside the surface, + cos = -cos; + neta = eta; + Nn = -N; + *is_inside = true; + } + *R = (2 * cos)* Nn - I; + float arg = 1 -(neta * neta *(1 -(cos * cos))); + if(arg < 0) { + *T = make_float3(0.0f, 0.0f, 0.0f); +#ifdef __RAY_DIFFERENTIALS__ + *dTdx = make_float3(0.0f, 0.0f, 0.0f); + *dTdy = make_float3(0.0f, 0.0f, 0.0f); +#endif + return 1; // total internal reflection + } + else { + float dnp = sqrtf(arg); + float nK = (neta * cos)- dnp; + *T = -(neta * I)+(nK * Nn); +#ifdef __RAY_DIFFERENTIALS__ + *dTdx = -(neta * dIdx) + ((neta - neta * neta * cos / dnp) * dot(dIdx, Nn)) * Nn; + *dTdy = -(neta * dIdy) + ((neta - neta * neta * cos / dnp) * dot(dIdy, Nn)) * Nn; +#endif + // compute Fresnel terms + float cosTheta1 = cos; // N.R + float cosTheta2 = -dot(Nn, *T); + float pPara = (cosTheta1 - eta * cosTheta2)/(cosTheta1 + eta * cosTheta2); + float pPerp = (eta * cosTheta1 - cosTheta2)/(eta * cosTheta1 + cosTheta2); + return 0.5f * (pPara * pPara + pPerp * pPerp); + } +} + +__device float fresnel_dielectric_cos(float cosi, float eta) +{ + // compute fresnel reflectance without explicitly computing + // the refracted direction + float c = fabsf(cosi); + float g = eta * eta - 1 + c * c; + if(g > 0) { + g = sqrtf(g); + float A = (g - c)/(g + c); + float B = (c *(g + c)- 1)/(c *(g - c)+ 1); + return 0.5f * A * A *(1 + B * B); + } + return 1.0f; // TIR(no refracted component) +} + +__device float fresnel_conductor(float cosi, float eta, float k) +{ + float tmp_f = eta * eta + k * k; + float tmp = tmp_f * cosi * cosi; + float Rparl2 = (tmp - (2.0f * eta * cosi) + 1)/ + (tmp + (2.0f * eta * cosi) + 1); + float Rperp2 = (tmp_f - (2.0f * eta * cosi) + cosi * cosi)/ + (tmp_f + (2.0f * eta * cosi) + cosi * cosi); + return(Rparl2 + Rperp2) * 0.5f; +} + +__device float smooth_step(float edge0, float edge1, float x) +{ + float result; + if(x < edge0) result = 0.0f; + else if(x >= edge1) result = 1.0f; + else { + float t = (x - edge0)/(edge1 - edge0); + result = (3.0f-2.0f*t)*(t*t); + } + return result; +} + +CCL_NAMESPACE_END + +#endif /* __OSL_BSDF_H__ */ + diff --git a/intern/cycles/kernel/closure/emissive.h b/intern/cycles/kernel/closure/emissive.h index cbf9d9a4efb..33b1b695a9a 100644 --- a/intern/cycles/kernel/closure/emissive.h +++ b/intern/cycles/kernel/closure/emissive.h @@ -49,17 +49,12 @@ __device void emissive_sample(const float3 Ng, float randu, float randv, /* todo: not implemented and used yet */ } -__device float3 emissive_eval(const float3 Ng, const float3 I) +__device float3 emissive_simple_eval(const float3 Ng, const float3 I) { float res = emissive_pdf(Ng, I); return make_float3(res, res, res); } -__device float3 svm_emissive_eval(ShaderData *sd, ShaderClosure *sc) -{ - return emissive_eval(sd->Ng, sd->I); -} - CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/closure/volume.h b/intern/cycles/kernel/closure/volume.h index 734f9111ab6..0b553f38a25 100644 --- a/intern/cycles/kernel/closure/volume.h +++ b/intern/cycles/kernel/closure/volume.h @@ -53,8 +53,13 @@ __device float3 volume_transparent_eval_phase(const ShaderClosure *sc, const flo /* VOLUME CLOSURE */ -__device float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) +__device float3 volume_eval_phase(KernelGlobals *kg, const ShaderClosure *sc, const float3 omega_in, const float3 omega_out) { +#ifdef __OSL__ + if(kg->osl && sc->prim) + return OSLShader::volume_eval_phase(sc, omega_in, omega_out); +#endif + float3 eval; switch(sc->type) { diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index a55f7a7fd75..fc2be342e02 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -35,7 +35,7 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou /* evaluate */ float3 P = sd.P; - shader_eval_displacement(kg, &sd); + shader_eval_displacement(kg, &sd, SHADER_CONTEXT_MAIN); out = sd.P - P; } else { // SHADER_EVAL_BACKGROUND @@ -63,7 +63,7 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou /* evaluate */ int flag = 0; /* we can't know which type of BSDF this is for */ - out = shader_eval_background(kg, &sd, flag); + out = shader_eval_background(kg, &sd, flag, SHADER_CONTEXT_MAIN); } shader_release(kg, &sd); diff --git a/intern/cycles/kernel/kernel_emission.h b/intern/cycles/kernel/kernel_emission.h index 6d650a0158d..e56633c9358 100644 --- a/intern/cycles/kernel/kernel_emission.h +++ b/intern/cycles/kernel/kernel_emission.h @@ -42,7 +42,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, ray.time = time; #endif shader_setup_from_background(kg, &sd, &ray); - eval = shader_eval_background(kg, &sd, 0); + eval = shader_eval_background(kg, &sd, 0, SHADER_CONTEXT_EMISSION); } else #endif @@ -52,7 +52,7 @@ __device float3 direct_emissive_eval(KernelGlobals *kg, float rando, /* no path flag, we're evaluating this for all closures. that's weak but * we'd have to do multiple evaluations otherwise */ - shader_eval_surface(kg, &sd, rando, 0); + shader_eval_surface(kg, &sd, rando, 0, SHADER_CONTEXT_EMISSION); /* evaluate emissive closure */ if(sd.flag & SD_EMISSION) @@ -170,7 +170,7 @@ __device float3 indirect_background(KernelGlobals *kg, Ray *ray, int path_flag, /* evaluate background closure */ ShaderData sd; shader_setup_from_background(kg, &sd, ray); - float3 L = shader_eval_background(kg, &sd, path_flag); + float3 L = shader_eval_background(kg, &sd, path_flag, SHADER_CONTEXT_EMISSION); shader_release(kg, &sd); #ifdef __BACKGROUND_MIS__ diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 3588b09c790..8da21751cbe 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -207,7 +207,7 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, ray); - shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW); + shader_eval_surface(kg, &sd, 0.0f, PATH_RAY_SHADOW, SHADER_CONTEXT_SHADOW); throughput *= shader_bsdf_transparency(kg, &sd); @@ -272,7 +272,7 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &ray); float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF); - shader_eval_surface(kg, &sd, rbsdf, state.flag); + shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN); kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput); @@ -478,7 +478,7 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &ray); float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF); - shader_eval_surface(kg, &sd, rbsdf, state.flag); + shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_INDIRECT); shader_merge_closures(kg, &sd); /* blurring of bsdf after bounces, for rays that have a small likelihood @@ -666,7 +666,7 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam ShaderData sd; shader_setup_from_ray(kg, &sd, &isect, &ray); float rbsdf = path_rng(kg, rng, sample, rng_offset + PRNG_BSDF); - shader_eval_surface(kg, &sd, rbsdf, state.flag); + shader_eval_surface(kg, &sd, rbsdf, state.flag, SHADER_CONTEXT_MAIN); shader_merge_closures(kg, &sd); kernel_write_data_passes(kg, buffer, &L, &sd, sample, state.flag, throughput); diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 98a7ec59d7b..9bbfe6b0cc5 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -26,11 +26,11 @@ * */ +#include "closure/bsdf_util.h" #include "closure/bsdf.h" #include "closure/emissive.h" #include "closure/volume.h" -#include "svm/svm_bsdf.h" #include "svm/svm.h" CCL_NAMESPACE_BEGIN @@ -56,11 +56,6 @@ __device_noinline void shader_setup_object_transforms(KernelGlobals *kg, ShaderD __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { -#ifdef __OSL__ - if (kg->osl) - OSLShader::init(kg, sd); -#endif - /* fetch triangle data */ int prim = kernel_tex_fetch(__prim_index, isect->prim); float4 Ns = kernel_tex_fetch(__tri_normal, prim); @@ -142,11 +137,6 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, const float3 P, const float3 Ng, const float3 I, int shader, int object, int prim, float u, float v, float t, float time) { -#ifdef __OSL__ - if (kg->osl) - OSLShader::init(kg, sd); -#endif - /* vectors */ sd->P = P; sd->N = Ng; @@ -273,11 +263,6 @@ __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData *sd, const Ray *ray) { -#ifdef __OSL__ - if (kg->osl) - OSLShader::init(kg, sd); -#endif - /* vectors */ sd->P = ray->D; sd->N = -sd->P; @@ -320,36 +305,8 @@ __device_inline void shader_setup_from_background(KernelGlobals *kg, ShaderData #ifdef __MULTI_CLOSURE__ -#ifdef __OSL__ -__device_inline void _shader_bsdf_multi_eval_osl(const ShaderData *sd, const float3 omega_in, float *pdf, - int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight) -{ - for(int i = 0; i< sd->num_closure; i++) { - if(i == skip_bsdf) - continue; - - const ShaderClosure *sc = &sd->closure[i]; - - if(CLOSURE_IS_BSDF(sc->type)) { - float bsdf_pdf = 0.0f; - - float3 eval = OSLShader::bsdf_eval(sd, sc, omega_in, bsdf_pdf); - - if(bsdf_pdf != 0.0f) { - bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight); - sum_pdf += bsdf_pdf*sc->sample_weight; - } - - sum_sample_weight += sc->sample_weight; - } - } - - *pdf = (sum_sample_weight > 0.0f)? sum_pdf/sum_sample_weight: 0.0f; -} -#endif - -__device_inline void _shader_bsdf_multi_eval_svm(const ShaderData *sd, const float3 omega_in, float *pdf, - int skip_bsdf, BsdfEval *bsdf_eval, float sum_pdf, float sum_sample_weight) +__device_inline void _shader_bsdf_multi_eval(KernelGlobals *kg, const ShaderData *sd, const float3 omega_in, float *pdf, + int skip_bsdf, BsdfEval *result_eval, float sum_pdf, float sum_sample_weight) { for(int i = 0; i< sd->num_closure; i++) { if(i == skip_bsdf) @@ -359,11 +316,10 @@ __device_inline void _shader_bsdf_multi_eval_svm(const ShaderData *sd, const flo if(CLOSURE_IS_BSDF(sc->type)) { float bsdf_pdf = 0.0f; - - float3 eval = svm_bsdf_eval(sd, sc, omega_in, &bsdf_pdf); + float3 eval = bsdf_eval(kg, sd, sc, omega_in, &bsdf_pdf); if(bsdf_pdf != 0.0f) { - bsdf_eval_accum(bsdf_eval, sc->type, eval*sc->weight); + bsdf_eval_accum(result_eval, sc->type, eval*sc->weight); sum_pdf += bsdf_pdf*sc->sample_weight; } @@ -382,17 +338,12 @@ __device void shader_bsdf_eval(KernelGlobals *kg, const ShaderData *sd, #ifdef __MULTI_CLOSURE__ bsdf_eval_init(eval, NBUILTIN_CLOSURES, make_float3(0.0f, 0.0f, 0.0f), kernel_data.film.use_light_pass); -#ifdef __OSL__ - if (kg->osl) - return _shader_bsdf_multi_eval_osl(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); - else -#endif - return _shader_bsdf_multi_eval_svm(sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); + return _shader_bsdf_multi_eval(kg, sd, omega_in, pdf, -1, eval, 0.0f, 0.0f); #else const ShaderClosure *sc = &sd->closure; *pdf = 0.0f; - *eval = svm_bsdf_eval(sd, sc, omega_in, pdf)*sc->weight; + *eval = bsdf_eval(kg, sd, sc, omega_in, pdf)*sc->weight; #endif } @@ -439,24 +390,14 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, float3 eval; *pdf = 0.0f; -#ifdef __OSL__ - if (kg->osl) - label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); - else -#endif - label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); if(*pdf != 0.0f) { bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass); if(sd->num_closure > 1) { float sweight = sc->sample_weight; -#ifdef __OSL__ - if (kg->osl) - _shader_bsdf_multi_eval_osl(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); - else -#endif - _shader_bsdf_multi_eval_svm(sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); + _shader_bsdf_multi_eval(kg, sd, *omega_in, pdf, sampled, bsdf_eval, *pdf*sweight, sweight); } } @@ -464,7 +405,7 @@ __device int shader_bsdf_sample(KernelGlobals *kg, const ShaderData *sd, #else /* sample the single closure that we picked */ *pdf = 0.0f; - int label = svm_bsdf_sample(sd, &sd->closure, randu, randv, bsdf_eval, omega_in, domega_in, pdf); + int label = bsdf_sample(kg, sd, &sd->closure, randu, randv, bsdf_eval, omega_in, domega_in, pdf); *bsdf_eval *= sd->closure.weight; return label; #endif @@ -478,12 +419,7 @@ __device int shader_bsdf_sample_closure(KernelGlobals *kg, const ShaderData *sd, float3 eval; *pdf = 0.0f; -#ifdef __OSL__ - if (kg->osl) - label = OSLShader::bsdf_sample(sd, sc, randu, randv, eval, *omega_in, *domega_in, *pdf); - else -#endif - label = svm_bsdf_sample(sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); + label = bsdf_sample(kg, sd, sc, randu, randv, &eval, omega_in, domega_in, pdf); if(*pdf != 0.0f) bsdf_eval_init(bsdf_eval, sc->type, eval*sc->weight, kernel_data.film.use_light_pass); @@ -497,17 +433,11 @@ __device void shader_bsdf_blur(KernelGlobals *kg, ShaderData *sd, float roughnes for(int i = 0; i< sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_BSDF(sc->type)) { -#ifdef __OSL__ - if (kg->osl) - OSLShader::bsdf_blur(sc, roughness); - else -#endif - svm_bsdf_blur(sc, roughness); - } + if(CLOSURE_IS_BSDF(sc->type)) + bsdf_blur(kg, sc, roughness); } #else - svm_bsdf_blur(&sd->closure, roughness); + bsdf_blur(kg, &sd->closure, roughness); #endif } @@ -635,6 +565,16 @@ __device float3 shader_bsdf_ao(KernelGlobals *kg, ShaderData *sd, float ao_facto /* Emission */ +__device float3 emissive_eval(KernelGlobals *kg, ShaderData *sd, ShaderClosure *sc) +{ +#ifdef __OSL__ + if(kg->osl && sc->prim) + return OSLShader::emissive_eval(sd, sc); +#endif + + return emissive_simple_eval(sd->Ng, sd->I); +} + __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) { float3 eval; @@ -644,18 +584,11 @@ __device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd) for(int i = 0; i < sd->num_closure; i++) { ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_EMISSION(sc->type)) { -#ifdef __OSL__ - if (kg->osl) - eval += OSLShader::emissive_eval(sd, sc)*sc->weight; - else -#endif - eval += svm_emissive_eval(sd, sc)*sc->weight; - - } + if(CLOSURE_IS_EMISSION(sc->type)) + eval += emissive_eval(kg, sd, sc)*sc->weight; } #else - eval = svm_emissive_eval(sd, &sd->closure)*sd->closure.weight; + eval = emissive_eval(kg, sd, &sd->closure)*sd->closure.weight; #endif return eval; @@ -687,11 +620,11 @@ __device float3 shader_holdout_eval(KernelGlobals *kg, ShaderData *sd) /* Surface Evaluation */ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, - float randb, int path_flag) + float randb, int path_flag, ShaderContext ctx) { #ifdef __OSL__ if (kg->osl) - OSLShader::eval_surface(kg, sd, randb, path_flag); + OSLShader::eval_surface(kg, sd, randb, path_flag, ctx); else #endif { @@ -706,11 +639,11 @@ __device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd, /* Background Evaluation */ -__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) +__device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx) { #ifdef __OSL__ if (kg->osl) - return OSLShader::eval_background(kg, sd, path_flag); + return OSLShader::eval_background(kg, sd, path_flag, ctx); else #endif @@ -753,31 +686,25 @@ __device float3 shader_volume_eval_phase(KernelGlobals *kg, ShaderData *sd, for(int i = 0; i< sd->num_closure; i++) { const ShaderClosure *sc = &sd->closure[i]; - if(CLOSURE_IS_VOLUME(sc->type)) { -#ifdef __OSL__ - if (kg->osl) - eval += OSLShader::volume_eval_phase(sc, omega_in, omega_out); - else -#endif - eval += volume_eval_phase(sc, omega_in, omega_out); - } + if(CLOSURE_IS_VOLUME(sc->type)) + eval += volume_eval_phase(kg, sc, omega_in, omega_out); } return eval; #else - return volume_eval_phase(&sd->closure, omega_in, omega_out); + return volume_eval_phase(kg, &sd->closure, omega_in, omega_out); #endif } /* Volume Evaluation */ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, - float randb, int path_flag) + float randb, int path_flag, ShaderContext ctx) { #ifdef __SVM__ #ifdef __OSL__ if (kg->osl) - OSLShader::eval_volume(kg, sd, randb, path_flag); + OSLShader::eval_volume(kg, sd, randb, path_flag, ctx); else #endif svm_eval_nodes(kg, sd, SHADER_TYPE_VOLUME, randb, path_flag); @@ -786,13 +713,13 @@ __device void shader_eval_volume(KernelGlobals *kg, ShaderData *sd, /* Displacement Evaluation */ -__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd) +__device void shader_eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx) { /* this will modify sd->P */ #ifdef __SVM__ #ifdef __OSL__ if (kg->osl) - OSLShader::eval_displacement(kg, sd); + OSLShader::eval_displacement(kg, sd, ctx); else #endif svm_eval_nodes(kg, sd, SHADER_TYPE_DISPLACEMENT, 0.0f, 0); @@ -818,7 +745,6 @@ __device bool shader_transparent_shadow(KernelGlobals *kg, Intersection *isect) #ifdef __NON_PROGRESSIVE__ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) { -#ifndef __OSL__ /* merge identical closures, better when we sample a single closure at a time */ for(int i = 0; i < sd->num_closure; i++) { ShaderClosure *sci = &sd->closure[i]; @@ -826,7 +752,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) for(int j = i + 1; j < sd->num_closure; j++) { ShaderClosure *scj = &sd->closure[j]; - if(sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) { + if(!sci->prim && sci->type == scj->type && sci->data0 == scj->data0 && sci->data1 == scj->data1) { sci->weight += scj->weight; sci->sample_weight += scj->sample_weight; @@ -838,7 +764,6 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) } } } -#endif } #endif @@ -846,10 +771,7 @@ __device void shader_merge_closures(KernelGlobals *kg, ShaderData *sd) __device void shader_release(KernelGlobals *kg, ShaderData *sd) { -#ifdef __OSL__ - if (kg->osl) - OSLShader::release(kg, sd); -#endif + /* nothing to do currently */ } CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/kernel_types.h b/intern/cycles/kernel/kernel_types.h index e3a766e56b1..a0673f55681 100644 --- a/intern/cycles/kernel/kernel_types.h +++ b/intern/cycles/kernel/kernel_types.h @@ -379,6 +379,18 @@ typedef struct ShaderClosure { #endif } ShaderClosure; +/* Shader Context + * + * For OSL we recycle a fixed number of contexts for speed */ + +typedef enum ShaderContext { + SHADER_CONTEXT_MAIN = 0, + SHADER_CONTEXT_INDIRECT = 1, + SHADER_CONTEXT_EMISSION = 2, + SHADER_CONTEXT_SHADOW = 3, + SHADER_CONTEXT_NUM = 4 +} ShaderContext; + /* Shader Data * * Main shader state at a point on the surface or in a volume. All coordinates @@ -466,11 +478,6 @@ typedef struct ShaderData { /* Closure data, with a single sampled closure for low memory usage */ ShaderClosure closure; #endif - -#ifdef __OSL__ - /* OSL context */ - void *osl_ctx; -#endif } ShaderData; /* Constrant Kernel Data diff --git a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp index 7189f99a822..a320bea118a 100644 --- a/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp +++ b/intern/cycles/kernel/osl/bsdf_diffuse_ramp.cpp @@ -55,7 +55,7 @@ public: void setup() { - sc.N = TO_FLOAT3(N); + sc.prim = this; m_shaderdata_flag = bsdf_diffuse_ramp_setup(&sc); for(int i = 0; i < 8; i++) @@ -101,7 +101,7 @@ public: ClosureParam *closure_bsdf_diffuse_ramp_params() { static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(DiffuseRampClosure, N), + CLOSURE_FLOAT3_PARAM(DiffuseRampClosure, sc.N), CLOSURE_COLOR_ARRAY_PARAM(DiffuseRampClosure, colors, 8), CLOSURE_STRING_KEYPARAM("label"), CLOSURE_FINISH_PARAM(DiffuseRampClosure) diff --git a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp index fb144be7e50..ef656ee7d5f 100644 --- a/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp +++ b/intern/cycles/kernel/osl/bsdf_phong_ramp.cpp @@ -54,7 +54,7 @@ public: void setup() { - sc.N = TO_FLOAT3(N); + sc.prim = this; m_shaderdata_flag = bsdf_phong_ramp_setup(&sc); for(int i = 0; i < 8; i++) @@ -100,7 +100,7 @@ public: ClosureParam *closure_bsdf_phong_ramp_params() { static ClosureParam params[] = { - CLOSURE_VECTOR_PARAM(PhongRampClosure, N), + CLOSURE_FLOAT3_PARAM(PhongRampClosure, sc.N), CLOSURE_FLOAT_PARAM(PhongRampClosure, sc.data0), CLOSURE_COLOR_ARRAY_PARAM(PhongRampClosure, colors, 8), CLOSURE_STRING_KEYPARAM("label"), diff --git a/intern/cycles/kernel/osl/emissive.cpp b/intern/cycles/kernel/osl/emissive.cpp index 37e3e37c00a..7d9fa81dbdd 100644 --- a/intern/cycles/kernel/osl/emissive.cpp +++ b/intern/cycles/kernel/osl/emissive.cpp @@ -65,7 +65,7 @@ public: Color3 eval(const Vec3 &Ng, const Vec3 &omega_out) const { - float3 result = emissive_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out)); + float3 result = emissive_simple_eval(TO_FLOAT3(Ng), TO_FLOAT3(omega_out)); return TO_COLOR3(result); } diff --git a/intern/cycles/kernel/osl/osl_closures.cpp b/intern/cycles/kernel/osl/osl_closures.cpp index 1f71fde549e..fa9f770d6ed 100644 --- a/intern/cycles/kernel/osl/osl_closures.cpp +++ b/intern/cycles/kernel/osl/osl_closures.cpp @@ -43,7 +43,7 @@ #include "kernel_types.h" #include "kernel_montecarlo.h" -#include "closure/bsdf.h" +#include "closure/bsdf_util.h" #include "closure/bsdf_ashikhmin_velvet.h" #include "closure/bsdf_diffuse.h" #include "closure/bsdf_microfacet.h" @@ -62,34 +62,34 @@ using namespace OSL; /* BSDF class definitions */ BSDF_CLOSURE_CLASS_BEGIN(Diffuse, diffuse, diffuse, LABEL_DIFFUSE) - CLOSURE_VECTOR_PARAM(DiffuseClosure, N), + CLOSURE_FLOAT3_PARAM(DiffuseClosure, sc.N), BSDF_CLOSURE_CLASS_END(Diffuse, diffuse) BSDF_CLOSURE_CLASS_BEGIN(Translucent, translucent, translucent, LABEL_DIFFUSE) - CLOSURE_VECTOR_PARAM(TranslucentClosure, N), + CLOSURE_FLOAT3_PARAM(TranslucentClosure, sc.N), BSDF_CLOSURE_CLASS_END(Translucent, translucent) BSDF_CLOSURE_CLASS_BEGIN(OrenNayar, oren_nayar, oren_nayar, LABEL_DIFFUSE) - CLOSURE_VECTOR_PARAM(OrenNayarClosure, N), + CLOSURE_FLOAT3_PARAM(OrenNayarClosure, sc.N), CLOSURE_FLOAT_PARAM(OrenNayarClosure, sc.data0), BSDF_CLOSURE_CLASS_END(OrenNayar, oren_nayar) BSDF_CLOSURE_CLASS_BEGIN(Reflection, reflection, reflection, LABEL_SINGULAR) - CLOSURE_VECTOR_PARAM(ReflectionClosure, N), + CLOSURE_FLOAT3_PARAM(ReflectionClosure, sc.N), BSDF_CLOSURE_CLASS_END(Reflection, reflection) BSDF_CLOSURE_CLASS_BEGIN(Refraction, refraction, refraction, LABEL_SINGULAR) - CLOSURE_VECTOR_PARAM(RefractionClosure, N), + CLOSURE_FLOAT3_PARAM(RefractionClosure, sc.N), CLOSURE_FLOAT_PARAM(RefractionClosure, sc.data0), BSDF_CLOSURE_CLASS_END(Refraction, refraction) BSDF_CLOSURE_CLASS_BEGIN(WestinBackscatter, westin_backscatter, westin_backscatter, LABEL_GLOSSY) - CLOSURE_VECTOR_PARAM(WestinBackscatterClosure, N), + CLOSURE_FLOAT3_PARAM(WestinBackscatterClosure, sc.N), CLOSURE_FLOAT_PARAM(WestinBackscatterClosure, sc.data0), BSDF_CLOSURE_CLASS_END(WestinBackscatter, westin_backscatter) BSDF_CLOSURE_CLASS_BEGIN(WestinSheen, westin_sheen, westin_sheen, LABEL_DIFFUSE) - CLOSURE_VECTOR_PARAM(WestinSheenClosure, N), + CLOSURE_FLOAT3_PARAM(WestinSheenClosure, sc.N), CLOSURE_FLOAT_PARAM(WestinSheenClosure, sc.data0), BSDF_CLOSURE_CLASS_END(WestinSheen, westin_sheen) @@ -97,35 +97,35 @@ BSDF_CLOSURE_CLASS_BEGIN(Transparent, transparent, transparent, LABEL_SINGULAR) BSDF_CLOSURE_CLASS_END(Transparent, transparent) BSDF_CLOSURE_CLASS_BEGIN(AshikhminVelvet, ashikhmin_velvet, ashikhmin_velvet, LABEL_DIFFUSE) - CLOSURE_VECTOR_PARAM(AshikhminVelvetClosure, N), + CLOSURE_FLOAT3_PARAM(AshikhminVelvetClosure, sc.N), CLOSURE_FLOAT_PARAM(AshikhminVelvetClosure, sc.data0), BSDF_CLOSURE_CLASS_END(AshikhminVelvet, ashikhmin_velvet) BSDF_CLOSURE_CLASS_BEGIN(Ward, ward, ward, LABEL_GLOSSY) - CLOSURE_VECTOR_PARAM(WardClosure, N), - CLOSURE_VECTOR_PARAM(WardClosure, T), + CLOSURE_FLOAT3_PARAM(WardClosure, sc.N), + CLOSURE_FLOAT3_PARAM(WardClosure, sc.T), CLOSURE_FLOAT_PARAM(WardClosure, sc.data0), CLOSURE_FLOAT_PARAM(WardClosure, sc.data1), BSDF_CLOSURE_CLASS_END(Ward, ward) BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGX, microfacet_ggx, microfacet_ggx, LABEL_GLOSSY) - CLOSURE_VECTOR_PARAM(MicrofacetGGXClosure, N), + CLOSURE_FLOAT3_PARAM(MicrofacetGGXClosure, sc.N), CLOSURE_FLOAT_PARAM(MicrofacetGGXClosure, sc.data0), BSDF_CLOSURE_CLASS_END(MicrofacetGGX, microfacet_ggx) BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmann, microfacet_beckmann, microfacet_beckmann, LABEL_GLOSSY) - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannClosure, N), + CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannClosure, sc.N), CLOSURE_FLOAT_PARAM(MicrofacetBeckmannClosure, sc.data0), BSDF_CLOSURE_CLASS_END(MicrofacetBeckmann, microfacet_beckmann) BSDF_CLOSURE_CLASS_BEGIN(MicrofacetGGXRefraction, microfacet_ggx_refraction, microfacet_ggx, LABEL_GLOSSY) - CLOSURE_VECTOR_PARAM(MicrofacetGGXRefractionClosure, N), + CLOSURE_FLOAT3_PARAM(MicrofacetGGXRefractionClosure, sc.N), CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data0), CLOSURE_FLOAT_PARAM(MicrofacetGGXRefractionClosure, sc.data1), BSDF_CLOSURE_CLASS_END(MicrofacetGGXRefraction, microfacet_ggx_refraction) BSDF_CLOSURE_CLASS_BEGIN(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction, microfacet_beckmann, LABEL_GLOSSY) - CLOSURE_VECTOR_PARAM(MicrofacetBeckmannRefractionClosure, N), + CLOSURE_FLOAT3_PARAM(MicrofacetBeckmannRefractionClosure, sc.N), CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data0), CLOSURE_FLOAT_PARAM(MicrofacetBeckmannRefractionClosure, sc.data1), BSDF_CLOSURE_CLASS_END(MicrofacetBeckmannRefraction, microfacet_beckmann_refraction) diff --git a/intern/cycles/kernel/osl/osl_closures.h b/intern/cycles/kernel/osl/osl_closures.h index 5cd333c806e..fe37c974e95 100644 --- a/intern/cycles/kernel/osl/osl_closures.h +++ b/intern/cycles/kernel/osl/osl_closures.h @@ -70,8 +70,11 @@ void name(RendererServices *, int id, void *data) \ #define CLOSURE_PREPARE_STATIC(name, classname) static CLOSURE_PREPARE(name, classname) -#define TO_VEC3(v) (*(OSL::Vec3 *)&(v)) -#define TO_COLOR3(v) (*(OSL::Color3 *)&(v)) +#define CLOSURE_FLOAT3_PARAM(st, fld) \ + { TypeDesc::TypeVector, reckless_offsetof(st, fld), NULL, sizeof(OSL::Vec3) } + +#define TO_VEC3(v) OSL::Vec3(v.x, v.y, v.z) +#define TO_COLOR3(v) OSL::Color3(v.x, v.y, v.z) #define TO_FLOAT3(v) make_float3(v[0], v[1], v[2]) /* BSDF */ @@ -79,7 +82,6 @@ void name(RendererServices *, int id, void *data) \ class CBSDFClosure : public OSL::ClosurePrimitive { public: ShaderClosure sc; - OSL::Vec3 N, T; CBSDFClosure(int scattering) : OSL::ClosurePrimitive(BSDF), m_scattering_label(scattering), m_shaderdata_flag(0) { } @@ -87,7 +89,6 @@ public: int scattering() const { return m_scattering_label; } int shaderdata_flag() const { return m_shaderdata_flag; } - ClosureType shaderclosure_type() const { return sc.type; } virtual void blur(float roughness) = 0; virtual float3 eval_reflect(const float3 &omega_out, const float3 &omega_in, float &pdf) const = 0; @@ -114,8 +115,7 @@ public: \ \ void setup() \ { \ - sc.N = TO_FLOAT3(N); \ - sc.T = TO_FLOAT3(T); \ + sc.prim = NULL; \ m_shaderdata_flag = bsdf_##lower##_setup(&sc); \ } \ \ diff --git a/intern/cycles/kernel/osl/osl_globals.h b/intern/cycles/kernel/osl/osl_globals.h index 1a2a210de88..fb569117698 100644 --- a/intern/cycles/kernel/osl/osl_globals.h +++ b/intern/cycles/kernel/osl/osl_globals.h @@ -75,10 +75,21 @@ struct OSLGlobals { vector<ustring> object_names; }; +/* trace() call result */ +struct OSLTraceData { + Ray ray; + Intersection isect; + ShaderData sd; + bool setup; + bool init; +}; + /* thread key for thread specific data lookup */ struct OSLThreadData { OSL::ShaderGlobals globals; OSL::PerThreadInfo *thread_info; + OSLTraceData tracedata; + OSL::ShadingContext *context[SHADER_CONTEXT_NUM]; }; CCL_NAMESPACE_END diff --git a/intern/cycles/kernel/osl/osl_services.cpp b/intern/cycles/kernel/osl/osl_services.cpp index b584a54b1b7..d6e52e28c62 100644 --- a/intern/cycles/kernel/osl/osl_services.cpp +++ b/intern/cycles/kernel/osl/osl_services.cpp @@ -47,7 +47,7 @@ CCL_NAMESPACE_BEGIN /* RenderServices implementation */ -#define TO_MATRIX44(m) (*(OSL::Matrix44 *)&(m)) +#define COPY_MATRIX44(m1, m2) memcpy(m1, m2, sizeof(*m2)) /* static ustrings */ ustring OSLRenderServices::u_distance("distance"); @@ -121,7 +121,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); #endif tfm = transform_transpose(tfm); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -151,7 +151,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform Transform itfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif itfm = transform_transpose(itfm); - result = TO_MATRIX44(itfm); + COPY_MATRIX44(&result, &itfm); return true; } @@ -166,22 +166,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from, float ti if (from == u_ndc) { Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (from == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (from == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.screentoworld); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (from == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -194,22 +194,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to, fl if (to == u_ndc) { Transform tfm = transform_transpose(kernel_data.cam.worldtondc); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (to == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (to == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (to == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -232,7 +232,7 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, OSL::TransformationPtr Transform tfm = object_fetch_transform(kg, object, OBJECT_TRANSFORM); #endif tfm = transform_transpose(tfm); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -257,7 +257,7 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, OSL::Transform Transform tfm = object_fetch_transform(kg, object, OBJECT_INVERSE_TRANSFORM); #endif tfm = transform_transpose(tfm); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -272,22 +272,22 @@ bool OSLRenderServices::get_matrix(OSL::Matrix44 &result, ustring from) if (from == u_ndc) { Transform tfm = transform_transpose(transform_quick_inverse(kernel_data.cam.worldtondc)); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (from == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.rastertoworld); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (from == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.screentoworld); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (from == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.cameratoworld); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -300,22 +300,22 @@ bool OSLRenderServices::get_inverse_matrix(OSL::Matrix44 &result, ustring to) if (to == u_ndc) { Transform tfm = transform_transpose(kernel_data.cam.worldtondc); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (to == u_raster) { Transform tfm = transform_transpose(kernel_data.cam.worldtoraster); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (to == u_screen) { Transform tfm = transform_transpose(kernel_data.cam.worldtoscreen); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } else if (to == u_camera) { Transform tfm = transform_transpose(kernel_data.cam.worldtocamera); - result = TO_MATRIX44(tfm); + COPY_MATRIX44(&result, &tfm); return true; } @@ -815,13 +815,10 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg, ray.dD.dy = TO_FLOAT3(dRdy); /* allocate trace data */ - TraceData *tracedata = new TraceData(); + OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata; tracedata->ray = ray; tracedata->setup = false; - - if(sg->tracedata) - delete (TraceData*)sg->tracedata; - sg->tracedata = tracedata; + tracedata->init = true; /* raytrace */ return scene_intersect(kernel_globals, &ray, ~0, &tracedata->isect); @@ -831,9 +828,9 @@ bool OSLRenderServices::trace(TraceOpt &options, OSL::ShaderGlobals *sg, bool OSLRenderServices::getmessage(OSL::ShaderGlobals *sg, ustring source, ustring name, TypeDesc type, void *val, bool derivatives) { - TraceData *tracedata = (TraceData*)sg->tracedata; + OSLTraceData *tracedata = (OSLTraceData*)sg->tracedata; - if(source == u_trace && tracedata) { + if(source == u_trace && tracedata->init) { if(name == u_hit) { return set_attribute_int((tracedata->isect.prim != ~0), type, derivatives, val); } diff --git a/intern/cycles/kernel/osl/osl_services.h b/intern/cycles/kernel/osl/osl_services.h index e687700b383..cd4a4163209 100644 --- a/intern/cycles/kernel/osl/osl_services.h +++ b/intern/cycles/kernel/osl/osl_services.h @@ -106,13 +106,6 @@ public: static bool get_object_standard_attribute(KernelGlobals *kg, ShaderData *sd, ustring name, TypeDesc type, bool derivatives, void *val); - struct TraceData { - Ray ray; - Intersection isect; - ShaderData sd; - bool setup; - }; - static ustring u_distance; static ustring u_index; static ustring u_camera; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index 32712b25e92..f5c04b6755e 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -51,8 +51,13 @@ void OSLShader::thread_init(KernelGlobals *kg, KernelGlobals *kernel_globals, OS OSLThreadData *tdata = new OSLThreadData(); memset(&tdata->globals, 0, sizeof(OSL::ShaderGlobals)); + tdata->globals.tracedata = &tdata->tracedata; + tdata->globals.flipHandedness = false; tdata->thread_info = ss->create_thread_info(); + for(int i = 0; i < SHADER_CONTEXT_NUM; i++) + tdata->context[i] = ss->get_context(tdata->thread_info); + kg->osl_ss = (OSLShadingSystem*)ss; kg->osl_tdata = tdata; } @@ -65,6 +70,9 @@ void OSLShader::thread_free(KernelGlobals *kg) OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; OSLThreadData *tdata = kg->osl_tdata; + for(int i = 0; i < SHADER_CONTEXT_NUM; i++) + ss->release_context(tdata->context[i]); + ss->destroy_thread_info(tdata->thread_info); delete tdata; @@ -77,8 +85,10 @@ void OSLShader::thread_free(KernelGlobals *kg) /* Globals */ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, - int path_flag, OSL::ShaderGlobals *globals) + int path_flag, OSLThreadData *tdata) { + OSL::ShaderGlobals *globals = &tdata->globals; + /* copy from shader data to shader globals */ globals->P = TO_VEC3(sd->P); globals->dPdx = TO_VEC3(sd->dP.dx); @@ -100,15 +110,11 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, globals->time = sd->time; /* booleans */ - globals->raytype = path_flag; /* todo: add our own ray types */ + globals->raytype = path_flag; globals->backfacing = (sd->flag & SD_BACKFACING); - /* don't know yet if we need this */ - globals->flipHandedness = false; - /* shader data to be used in services callbacks */ globals->renderstate = sd; - globals->tracedata = NULL; /* hacky, we leave it to services to fetch actual object matrix */ globals->shader2common = sd; @@ -116,6 +122,9 @@ static void shaderdata_to_shaderglobals(KernelGlobals *kg, ShaderData *sd, /* must be set to NULL before execute */ globals->Ci = NULL; + + /* clear trace data */ + tdata->tracedata.init = false; } /* Surface */ @@ -132,14 +141,10 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, if (prim) { ShaderClosure sc; - sc.prim = prim; sc.weight = weight; switch (prim->category()) { case OSL::ClosurePrimitive::BSDF: { - if (sd->num_closure == MAX_CLOSURE) - return; - CBSDFClosure *bsdf = (CBSDFClosure *)prim; int scattering = bsdf->scattering(); @@ -151,8 +156,13 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; - sc.type = bsdf->shaderclosure_type(); - sc.N = bsdf->sc.N; /* needed for AO */ + + 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.prim = bsdf->sc.prim; /* add */ if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) { @@ -170,6 +180,7 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, sc.sample_weight = sample_weight; sc.type = CLOSURE_EMISSION_ID; + sc.prim = NULL; /* flag */ if(sd->num_closure < MAX_CLOSURE) { @@ -179,14 +190,12 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, break; } case AmbientOcclusion: { - if (sd->num_closure == MAX_CLOSURE) - return; - /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_AMBIENT_OCCLUSION_ID; + sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; @@ -195,11 +204,9 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, break; } case OSL::ClosurePrimitive::Holdout: - if (sd->num_closure == MAX_CLOSURE) - return; - sc.sample_weight = 0.0f; sc.type = CLOSURE_HOLDOUT_ID; + sc.prim = NULL; if(sd->num_closure < MAX_CLOSURE) { sd->closure[sd->num_closure++] = sc; @@ -226,26 +233,20 @@ static void flatten_surface_closure_tree(ShaderData *sd, bool no_glossy, } } -void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) +void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx) { - /* gather pointers */ - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; - OSLThreadData *tdata = kg->osl_tdata; - OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; - /* setup shader globals from shader data */ - shaderdata_to_shaderglobals(kg, sd, path_flag, globals); + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, 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)ctx]; int shader = sd->shader & SHADER_MASK; if (kg->osl->surface_state[shader]) - ss->execute(*ctx, *(kg->osl->surface_state[shader]), *globals); - - /* free trace data */ - if(globals->tracedata) - delete (OSLRenderServices::TraceData*)globals->tracedata; + ss->execute(*octx, *(kg->osl->surface_state[shader]), *globals); /* flatten closure tree */ sd->num_closure = 0; @@ -287,24 +288,19 @@ static float3 flatten_background_closure_tree(const OSL::ClosureColor *closure) return make_float3(0.0f, 0.0f, 0.0f); } -float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag) +float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx) { - /* gather pointers */ - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; - OSLThreadData *tdata = kg->osl_tdata; - OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; - /* setup shader globals from shader data */ - shaderdata_to_shaderglobals(kg, sd, path_flag, globals); + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, path_flag, tdata); /* execute shader for this point */ - if (kg->osl->background_state) - ss->execute(*ctx, *(kg->osl->background_state), *globals); + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context[(int)ctx]; - /* free trace data */ - if(globals->tracedata) - delete (OSLRenderServices::TraceData*)globals->tracedata; + if (kg->osl->background_state) + ss->execute(*octx, *(kg->osl->background_state), *globals); /* return background color immediately */ if (globals->Ci) @@ -327,19 +323,16 @@ static void flatten_volume_closure_tree(ShaderData *sd, if (prim) { ShaderClosure sc; - sc.prim = prim; sc.weight = weight; switch (prim->category()) { case OSL::ClosurePrimitive::Volume: { - if (sd->num_closure == MAX_CLOSURE) - return; - /* sample weight */ float sample_weight = fabsf(average(weight)); sc.sample_weight = sample_weight; sc.type = CLOSURE_VOLUME_ID; + sc.prim = NULL; /* add */ if(sc.sample_weight > 1e-5f && sd->num_closure < MAX_CLOSURE) @@ -368,26 +361,20 @@ static void flatten_volume_closure_tree(ShaderData *sd, } } -void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag) +void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx) { - /* gather pointers */ - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; - OSLThreadData *tdata = kg->osl_tdata; - OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; - /* setup shader globals from shader data */ - shaderdata_to_shaderglobals(kg, sd, path_flag, globals); + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, path_flag, tdata); /* execute shader */ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; if (kg->osl->volume_state[shader]) - ss->execute(*ctx, *(kg->osl->volume_state[shader]), *globals); - - /* free trace data */ - if(globals->tracedata) - delete (OSLRenderServices::TraceData*)globals->tracedata; + ss->execute(*octx, *(kg->osl->volume_state[shader]), *globals); if (globals->Ci) flatten_volume_closure_tree(sd, globals->Ci); @@ -395,46 +382,25 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int /* Displacement */ -void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) +void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx) { - /* gather pointers */ - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; - OSLThreadData *tdata = kg->osl_tdata; - OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; - /* setup shader globals from shader data */ - shaderdata_to_shaderglobals(kg, sd, 0, globals); + OSLThreadData *tdata = kg->osl_tdata; + shaderdata_to_shaderglobals(kg, sd, 0, tdata); /* execute shader */ + OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; + OSL::ShaderGlobals *globals = &tdata->globals; + OSL::ShadingContext *octx = tdata->context[(int)ctx]; int shader = sd->shader & SHADER_MASK; if (kg->osl->displacement_state[shader]) - ss->execute(*ctx, *(kg->osl->displacement_state[shader]), *globals); - - /* free trace data */ - if(globals->tracedata) - delete (OSLRenderServices::TraceData*)globals->tracedata; + ss->execute(*octx, *(kg->osl->displacement_state[shader]), *globals); /* get back position */ sd->P = TO_FLOAT3(globals->P); } -void OSLShader::init(KernelGlobals *kg, ShaderData *sd) -{ - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; - OSLThreadData *tdata = kg->osl_tdata; - - sd->osl_ctx = ss->get_context(tdata->thread_info); -} - -void OSLShader::release(KernelGlobals *kg, ShaderData *sd) -{ - OSL::ShadingSystem *ss = (OSL::ShadingSystem*)kg->osl_ss; - - ss->release_context((OSL::ShadingContext *)sd->osl_ctx); -} - /* BSDF Closure */ int OSLShader::bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3& eval, float3& omega_in, differential3& domega_in, float& pdf) diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index e614f240dc1..2e46a2de42c 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -55,10 +55,10 @@ public: static void thread_free(KernelGlobals *kg); /* eval */ - static void eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag); - static float3 eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag); - static void eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag); - static void eval_displacement(KernelGlobals *kg, ShaderData *sd); + static void eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx); + static float3 eval_background(KernelGlobals *kg, ShaderData *sd, int path_flag, ShaderContext ctx); + static void eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int path_flag, ShaderContext ctx); + static void eval_displacement(KernelGlobals *kg, ShaderData *sd, ShaderContext ctx); /* sample & eval */ static int bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, @@ -73,10 +73,6 @@ public: static float3 volume_eval_phase(const ShaderClosure *sc, const float3 omega_in, const float3 omega_out); - /* release */ - static void init(KernelGlobals *kg, ShaderData *sd); - static void release(KernelGlobals *kg, ShaderData *sd); - /* attributes */ static int find_attribute(KernelGlobals *kg, const ShaderData *sd, uint id); }; diff --git a/intern/cycles/kernel/svm/svm_bsdf.h b/intern/cycles/kernel/svm/svm_bsdf.h deleted file mode 100644 index a9524f3ed37..00000000000 --- a/intern/cycles/kernel/svm/svm_bsdf.h +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2011, Blender Foundation. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "../closure/bsdf_ashikhmin_velvet.h" -#include "../closure/bsdf_diffuse.h" -#include "../closure/bsdf_oren_nayar.h" -#include "../closure/bsdf_phong_ramp.h" -#include "../closure/bsdf_diffuse_ramp.h" -#include "../closure/bsdf_microfacet.h" -#include "../closure/bsdf_reflection.h" -#include "../closure/bsdf_refraction.h" -#include "../closure/bsdf_transparent.h" -#ifdef __ANISOTROPIC__ -#include "../closure/bsdf_ward.h" -#endif -#include "../closure/bsdf_westin.h" - -CCL_NAMESPACE_BEGIN - -__device int svm_bsdf_sample(const ShaderData *sd, const ShaderClosure *sc, float randu, float randv, float3 *eval, float3 *omega_in, differential3 *domega_in, float *pdf) -{ - int label; - - switch(sc->type) { - case CLOSURE_BSDF_DIFFUSE_ID: - label = bsdf_diffuse_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; -#ifdef __SVM__ - case CLOSURE_BSDF_OREN_NAYAR_ID: - label = bsdf_oren_nayar_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - /*case CLOSURE_BSDF_PHONG_RAMP_ID: - label = bsdf_phong_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - label = bsdf_diffuse_ramp_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break;*/ - case CLOSURE_BSDF_TRANSLUCENT_ID: - label = bsdf_translucent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_REFLECTION_ID: - label = bsdf_reflection_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_REFRACTION_ID: - label = bsdf_refraction_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_TRANSPARENT_ID: - label = bsdf_transparent_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_MICROFACET_GGX_ID: - case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - label = bsdf_microfacet_ggx_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: - case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - label = bsdf_microfacet_beckmann_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; -#ifdef __ANISOTROPIC__ - case CLOSURE_BSDF_WARD_ID: - label = bsdf_ward_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; -#endif - case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - label = bsdf_ashikhmin_velvet_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - label = bsdf_westin_backscatter_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - label = bsdf_westin_sheen_sample(sc, sd->Ng, sd->I, sd->dI.dx, sd->dI.dy, randu, randv, - eval, omega_in, &domega_in->dx, &domega_in->dy, pdf); - break; -#endif - default: - label = LABEL_NONE; - break; - } - - return label; -} - -__device float3 svm_bsdf_eval(const ShaderData *sd, const ShaderClosure *sc, const float3 omega_in, float *pdf) -{ - float3 eval; - - if(dot(sd->Ng, omega_in) >= 0.0f) { - switch(sc->type) { - case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_reflect(sc, sd->I, omega_in, pdf); - break; -#ifdef __SVM__ - case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_reflect(sc, sd->I, omega_in, pdf); - break; - /*case CLOSURE_BSDF_PHONG_RAMP_ID: - eval = bsdf_phong_ramp_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - eval = bsdf_diffuse_ramp_eval_reflect(sc, sd->I, omega_in, pdf); - break;*/ - case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_MICROFACET_GGX_ID: - case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: - case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_reflect(sc, sd->I, omega_in, pdf); - break; -#ifdef __ANISOTROPIC__ - case CLOSURE_BSDF_WARD_ID: - eval = bsdf_ward_eval_reflect(sc, sd->I, omega_in, pdf); - break; -#endif - case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_reflect(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_reflect(sc, sd->I, omega_in, pdf); - break; -#endif - default: - eval = make_float3(0.0f, 0.0f, 0.0f); - break; - } - } - else { - switch(sc->type) { - case CLOSURE_BSDF_DIFFUSE_ID: - eval = bsdf_diffuse_eval_transmit(sc, sd->I, omega_in, pdf); - break; -#ifdef __SVM__ - case CLOSURE_BSDF_OREN_NAYAR_ID: - eval = bsdf_oren_nayar_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_TRANSLUCENT_ID: - eval = bsdf_translucent_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFLECTION_ID: - eval = bsdf_reflection_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_REFRACTION_ID: - eval = bsdf_refraction_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_TRANSPARENT_ID: - eval = bsdf_transparent_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_MICROFACET_GGX_ID: - case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - eval = bsdf_microfacet_ggx_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: - case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - eval = bsdf_microfacet_beckmann_eval_transmit(sc, sd->I, omega_in, pdf); - break; -#ifdef __ANISOTROPIC__ - case CLOSURE_BSDF_WARD_ID: - eval = bsdf_ward_eval_transmit(sc, sd->I, omega_in, pdf); - break; -#endif - case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - eval = bsdf_ashikhmin_velvet_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - eval = bsdf_westin_backscatter_eval_transmit(sc, sd->I, omega_in, pdf); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - eval = bsdf_westin_sheen_eval_transmit(sc, sd->I, omega_in, pdf); - break; -#endif - default: - eval = make_float3(0.0f, 0.0f, 0.0f); - break; - } - } - - return eval; -} - -__device void svm_bsdf_blur(ShaderClosure *sc, float roughness) -{ - switch(sc->type) { - case CLOSURE_BSDF_DIFFUSE_ID: - bsdf_diffuse_blur(sc, roughness); - break; -#ifdef __SVM__ - case CLOSURE_BSDF_OREN_NAYAR_ID: - bsdf_oren_nayar_blur(sc, roughness); - break; - /*case CLOSURE_BSDF_PHONG_RAMP_ID: - bsdf_phong_ramp_blur(sc, roughness); - break; - case CLOSURE_BSDF_DIFFUSE_RAMP_ID: - bsdf_diffuse_ramp_blur(sc, roughness); - break;*/ - case CLOSURE_BSDF_TRANSLUCENT_ID: - bsdf_translucent_blur(sc, roughness); - break; - case CLOSURE_BSDF_REFLECTION_ID: - bsdf_reflection_blur(sc, roughness); - break; - case CLOSURE_BSDF_REFRACTION_ID: - bsdf_refraction_blur(sc, roughness); - break; - case CLOSURE_BSDF_TRANSPARENT_ID: - bsdf_transparent_blur(sc, roughness); - break; - case CLOSURE_BSDF_MICROFACET_GGX_ID: - case CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID: - bsdf_microfacet_ggx_blur(sc, roughness); - break; - case CLOSURE_BSDF_MICROFACET_BECKMANN_ID: - case CLOSURE_BSDF_MICROFACET_BECKMANN_REFRACTION_ID: - bsdf_microfacet_beckmann_blur(sc, roughness); - break; -#ifdef __ANISOTROPIC__ - case CLOSURE_BSDF_WARD_ID: - bsdf_ward_blur(sc, roughness); - break; -#endif - case CLOSURE_BSDF_ASHIKHMIN_VELVET_ID: - bsdf_ashikhmin_velvet_blur(sc, roughness); - break; - case CLOSURE_BSDF_WESTIN_BACKSCATTER_ID: - bsdf_westin_backscatter_blur(sc, roughness); - break; - case CLOSURE_BSDF_WESTIN_SHEEN_ID: - bsdf_westin_sheen_blur(sc, roughness); - break; -#endif - default: - break; - } -} - -CCL_NAMESPACE_END - |