From f3a91f461ca94557a8125915544676cc765a5709 Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Wed, 5 Sep 2012 08:12:22 +0000 Subject: [PATCH] Fix for OSL memory leak. The context creation for OSL is now done in the shader_setup_* functions, since it should specific to the sample being worked on. The the context release then happens in the kernel_shader functions after shader evaluation is done. Care has to be taken to ensure the shader_release function is also called in cases where the path integration is cancelled early, this was the main cause for unreleased contexts and subsequent new allocations. --- intern/cycles/kernel/kernel_displace.h | 2 ++ intern/cycles/kernel/kernel_path.h | 30 +++++++++++++++++++------ intern/cycles/kernel/kernel_shader.h | 17 ++++++++++++++ intern/cycles/kernel/osl/osl_shader.cpp | 22 ++++++++++-------- intern/cycles/kernel/osl/osl_shader.h | 3 ++- 5 files changed, 57 insertions(+), 17 deletions(-) diff --git a/intern/cycles/kernel/kernel_displace.h b/intern/cycles/kernel/kernel_displace.h index f4b33605f5b..6461a1eea38 100644 --- a/intern/cycles/kernel/kernel_displace.h +++ b/intern/cycles/kernel/kernel_displace.h @@ -63,6 +63,8 @@ __device void kernel_shader_evaluate(KernelGlobals *kg, uint4 *input, float4 *ou out = shader_eval_background(kg, &sd, flag); } + shader_release(kg, &sd); + /* write output */ output[i] = make_float4(out.x, out.y, out.z, 0.0f); } diff --git a/intern/cycles/kernel/kernel_path.h b/intern/cycles/kernel/kernel_path.h index 6c81fa4cfca..d606c3d634a 100644 --- a/intern/cycles/kernel/kernel_path.h +++ b/intern/cycles/kernel/kernel_path.h @@ -209,6 +209,8 @@ __device_inline bool shadow_blocked(KernelGlobals *kg, PathState *state, Ray *ra if(ray->t != FLT_MAX) ray->D = normalize_len(Pend - ray->P, &ray->t); + shader_release(kg, &sd); + bounce++; } } @@ -294,8 +296,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, L_transparent += average(holdout_weight*throughput); } - if(sd.flag & SD_HOLDOUT_MASK) + if(sd.flag & SD_HOLDOUT_MASK) { + shader_release(kg, &sd); break; + } } #endif @@ -313,8 +317,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) + if(terminate >= probability) { + shader_release(kg, &sd); break; + } throughput /= probability; @@ -380,8 +386,10 @@ __device float4 kernel_path_progressive(KernelGlobals *kg, RNG *rng, int sample, #endif /* no BSDF? we can stop here */ - if(!(sd.flag & SD_BSDF)) + if(!(sd.flag & SD_BSDF)) { + shader_release(kg, &sd); break; + } /* sample BSDF */ float bsdf_pdf; @@ -486,8 +494,10 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) + if(terminate >= probability) { + shader_release(kg, &sd); break; + } throughput /= probability; @@ -554,8 +564,10 @@ __device void kernel_path_indirect(KernelGlobals *kg, RNG *rng, int sample, Ray #endif /* no BSDF? we can stop here */ - if(!(sd.flag & SD_BSDF)) + if(!(sd.flag & SD_BSDF)) { + shader_release(kg, &sd); break; + } /* sample BSDF */ float bsdf_pdf; @@ -661,8 +673,10 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam L_transparent += average(holdout_weight*throughput); } - if(sd.flag & SD_HOLDOUT_MASK) + if(sd.flag & SD_HOLDOUT_MASK) { + shader_release(kg, &sd); break; + } } #endif @@ -682,8 +696,10 @@ __device float4 kernel_path_non_progressive(KernelGlobals *kg, RNG *rng, int sam float probability = path_state_terminate_probability(kg, &state, throughput); float terminate = path_rng(kg, rng, sample, rng_offset + PRNG_TERMINATE); - if(terminate >= probability) + if(terminate >= probability) { + shader_release(kg, &sd); break; + } throughput /= probability; } diff --git a/intern/cycles/kernel/kernel_shader.h b/intern/cycles/kernel/kernel_shader.h index 5ab3c2c2545..b57e27bc8ed 100644 --- a/intern/cycles/kernel/kernel_shader.h +++ b/intern/cycles/kernel/kernel_shader.h @@ -46,6 +46,11 @@ CCL_NAMESPACE_BEGIN __device_inline void shader_setup_from_ray(KernelGlobals *kg, ShaderData *sd, const Intersection *isect, const Ray *ray) { +#ifdef __OSL__ + if (kernel_osl_use(kg)) + 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); @@ -129,6 +134,11 @@ __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 (kernel_osl_use(kg)) + OSLShader::init(kg, sd); +#endif + /* vectors */ sd->P = P; sd->N = Ng; @@ -233,6 +243,8 @@ __device void shader_setup_from_sample(KernelGlobals *kg, ShaderData *sd, __device void shader_setup_from_displace(KernelGlobals *kg, ShaderData *sd, int object, int prim, float u, float v) { + /* Note: no OSLShader::init call here, this is done in shader_setup_from_sample! */ + float3 P, Ng, I = make_float3(0.0f, 0.0f, 0.0f); int shader; @@ -251,6 +263,11 @@ __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 (kernel_osl_use(kg)) + OSLShader::init(kg, sd); +#endif + /* vectors */ sd->P = ray->D; sd->N = -sd->P; diff --git a/intern/cycles/kernel/osl/osl_shader.cpp b/intern/cycles/kernel/osl/osl_shader.cpp index a7c21e7b595..98ede0e4f60 100644 --- a/intern/cycles/kernel/osl/osl_shader.cpp +++ b/intern/cycles/kernel/osl/osl_shader.cpp @@ -204,10 +204,9 @@ void OSLShader::eval_surface(KernelGlobals *kg, ShaderData *sd, float randb, int OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ @@ -262,10 +261,9 @@ float3 OSLShader::eval_background(KernelGlobals *kg, ShaderData *sd, int path_fl OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader for this point */ @@ -339,10 +337,9 @@ void OSLShader::eval_volume(KernelGlobals *kg, ShaderData *sd, float randb, int OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, path_flag, globals); /* execute shader */ @@ -363,10 +360,9 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) OSL::ShadingSystem *ss = kg->osl.ss; OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); OSL::ShaderGlobals *globals = &tdata->globals; - OSL::ShadingContext *ctx = ss->get_context(tdata->thread_info); + OSL::ShadingContext *ctx = (OSL::ShadingContext *)sd->osl_ctx; /* setup shader globals from shader data */ - sd->osl_ctx = ctx; shaderdata_to_shaderglobals(kg, sd, 0, globals); /* execute shader */ @@ -379,7 +375,15 @@ void OSLShader::eval_displacement(KernelGlobals *kg, ShaderData *sd) sd->P = TO_FLOAT3(globals->P); } -void OSLShader::release(KernelGlobals *kg, const ShaderData *sd) +void OSLShader::init(KernelGlobals *kg, ShaderData *sd) +{ + OSL::ShadingSystem *ss = kg->osl.ss; + OSLGlobals::ThreadData *tdata = tls_get(OSLGlobals::ThreadData, kg->osl.thread_data); + + sd->osl_ctx = ss->get_context(tdata->thread_info); +} + +void OSLShader::release(KernelGlobals *kg, ShaderData *sd) { OSL::ShadingSystem *ss = kg->osl.ss; diff --git a/intern/cycles/kernel/osl/osl_shader.h b/intern/cycles/kernel/osl/osl_shader.h index 815557ed203..e55f98d4d02 100644 --- a/intern/cycles/kernel/osl/osl_shader.h +++ b/intern/cycles/kernel/osl/osl_shader.h @@ -79,7 +79,8 @@ public: const float3 omega_in, const float3 omega_out); /* release */ - static void release(KernelGlobals *kg, const ShaderData *sd); + static void init(KernelGlobals *kg, ShaderData *sd); + static void release(KernelGlobals *kg, ShaderData *sd); }; CCL_NAMESPACE_END