forked from bartvdbraak/blender
Cycles: optimization for constant background colors.
Skip shader evaluation then, as we already do for lights. Less than 1% faster in my tests, but might as well be consistent for both.
This commit is contained in:
parent
9c7517fb63
commit
7778a1a0a1
@ -351,7 +351,7 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
|||||||
out = make_float3(roughness, roughness, roughness);
|
out = make_float3(roughness, roughness, roughness);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
out = shader_emissive_eval(kg, &sd);
|
out = shader_emissive_eval(&sd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -475,8 +475,9 @@ ccl_device void kernel_bake_evaluate(KernelGlobals *kg, ccl_global uint4 *input,
|
|||||||
shader_setup_from_background(kg, &sd, &ray);
|
shader_setup_from_background(kg, &sd, &ray);
|
||||||
|
|
||||||
/* evaluate */
|
/* evaluate */
|
||||||
int flag = 0; /* we can't know which type of BSDF this is for */
|
int path_flag = 0; /* we can't know which type of BSDF this is for */
|
||||||
out = shader_eval_background(kg, &sd, &state, flag);
|
shader_eval_surface(kg, &sd, &state, path_flag | PATH_RAY_EMISSION);
|
||||||
|
out = shader_background_eval(&sd);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@ -554,8 +555,9 @@ ccl_device void kernel_background_evaluate(KernelGlobals *kg,
|
|||||||
shader_setup_from_background(kg, &sd, &ray);
|
shader_setup_from_background(kg, &sd, &ray);
|
||||||
|
|
||||||
/* evaluate */
|
/* evaluate */
|
||||||
int flag = 0; /* we can't know which type of BSDF this is for */
|
int path_flag = 0; /* we can't know which type of BSDF this is for */
|
||||||
float3 color = shader_eval_background(kg, &sd, &state, flag);
|
shader_eval_surface(kg, &sd, &state, path_flag | PATH_RAY_EMISSION);
|
||||||
|
float3 color = shader_background_eval(&sd);
|
||||||
|
|
||||||
/* write output */
|
/* write output */
|
||||||
output[i] += make_float4(color.x, color.y, color.z, 0.0f);
|
output[i] += make_float4(color.x, color.y, color.z, 0.0f);
|
||||||
|
@ -29,43 +29,36 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
|
|||||||
/* setup shading at emitter */
|
/* setup shading at emitter */
|
||||||
float3 eval;
|
float3 eval;
|
||||||
|
|
||||||
int shader_flag = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).flags;
|
if(shader_constant_emission_eval(kg, ls->shader, &eval)) {
|
||||||
|
|
||||||
#ifdef __BACKGROUND_MIS__
|
|
||||||
if(ls->type == LIGHT_BACKGROUND) {
|
|
||||||
Ray ray;
|
|
||||||
ray.D = ls->D;
|
|
||||||
ray.P = ls->P;
|
|
||||||
ray.t = 1.0f;
|
|
||||||
ray.time = time;
|
|
||||||
ray.dP = differential3_zero();
|
|
||||||
ray.dD = dI;
|
|
||||||
|
|
||||||
shader_setup_from_background(kg, emission_sd, &ray);
|
|
||||||
|
|
||||||
path_state_modify_bounce(state, true);
|
|
||||||
eval = shader_eval_background(kg, emission_sd, state, 0);
|
|
||||||
path_state_modify_bounce(state, false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if(shader_flag & SD_HAS_CONSTANT_EMISSION)
|
|
||||||
{
|
|
||||||
eval.x = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).constant_emission[0];
|
|
||||||
eval.y = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).constant_emission[1];
|
|
||||||
eval.z = kernel_tex_fetch(__shaders, (ls->shader & SHADER_MASK)).constant_emission[2];
|
|
||||||
if((ls->prim != PRIM_NONE) && dot(ls->Ng, I) < 0.0f) {
|
if((ls->prim != PRIM_NONE) && dot(ls->Ng, I) < 0.0f) {
|
||||||
ls->Ng = -ls->Ng;
|
ls->Ng = -ls->Ng;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
/* Setup shader data and call shader_eval_surface once, better
|
||||||
shader_setup_from_sample(kg, emission_sd,
|
* for GPU coherence and compile times. */
|
||||||
ls->P, ls->Ng, I,
|
#ifdef __BACKGROUND_MIS__
|
||||||
ls->shader, ls->object, ls->prim,
|
if(ls->type == LIGHT_BACKGROUND) {
|
||||||
ls->u, ls->v, t, time, false, ls->lamp);
|
Ray ray;
|
||||||
|
ray.D = ls->D;
|
||||||
|
ray.P = ls->P;
|
||||||
|
ray.t = 1.0f;
|
||||||
|
ray.time = time;
|
||||||
|
ray.dP = differential3_zero();
|
||||||
|
ray.dD = dI;
|
||||||
|
|
||||||
ls->Ng = emission_sd->Ng;
|
shader_setup_from_background(kg, emission_sd, &ray);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
shader_setup_from_sample(kg, emission_sd,
|
||||||
|
ls->P, ls->Ng, I,
|
||||||
|
ls->shader, ls->object, ls->prim,
|
||||||
|
ls->u, ls->v, t, time, false, ls->lamp);
|
||||||
|
|
||||||
|
ls->Ng = emission_sd->Ng;
|
||||||
|
}
|
||||||
|
|
||||||
/* No proper path flag, we're evaluating this for all closures. that's
|
/* No proper path flag, we're evaluating this for all closures. that's
|
||||||
* weak but we'd have to do multiple evaluations otherwise. */
|
* weak but we'd have to do multiple evaluations otherwise. */
|
||||||
@ -73,8 +66,16 @@ ccl_device_noinline float3 direct_emissive_eval(KernelGlobals *kg,
|
|||||||
shader_eval_surface(kg, emission_sd, state, PATH_RAY_EMISSION);
|
shader_eval_surface(kg, emission_sd, state, PATH_RAY_EMISSION);
|
||||||
path_state_modify_bounce(state, false);
|
path_state_modify_bounce(state, false);
|
||||||
|
|
||||||
/* Evaluate emissive closure. */
|
/* Evaluate closures. */
|
||||||
eval = shader_emissive_eval(kg, emission_sd);
|
#ifdef __BACKGROUND_MIS__
|
||||||
|
if (ls->type == LIGHT_BACKGROUND) {
|
||||||
|
eval = shader_background_eval(emission_sd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
eval = shader_emissive_eval(emission_sd);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eval *= ls->eval_fac;
|
eval *= ls->eval_fac;
|
||||||
@ -201,7 +202,7 @@ ccl_device_noinline bool direct_emission(KernelGlobals *kg,
|
|||||||
ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf)
|
ccl_device_noinline float3 indirect_primitive_emission(KernelGlobals *kg, ShaderData *sd, float t, int path_flag, float bsdf_pdf)
|
||||||
{
|
{
|
||||||
/* evaluate emissive closure */
|
/* evaluate emissive closure */
|
||||||
float3 L = shader_emissive_eval(kg, sd);
|
float3 L = shader_emissive_eval(sd);
|
||||||
|
|
||||||
#ifdef __HAIR__
|
#ifdef __HAIR__
|
||||||
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE))
|
if(!(path_flag & PATH_RAY_MIS_SKIP) && (sd->flag & SD_USE_MIS) && (sd->type & PRIMITIVE_ALL_TRIANGLE))
|
||||||
@ -294,7 +295,7 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
|
|||||||
#ifdef __BACKGROUND__
|
#ifdef __BACKGROUND__
|
||||||
int shader = kernel_data.background.surface_shader;
|
int shader = kernel_data.background.surface_shader;
|
||||||
|
|
||||||
/* use visibility flag to skip lights */
|
/* Use visibility flag to skip lights. */
|
||||||
if(shader & SHADER_EXCLUDE_ANY) {
|
if(shader & SHADER_EXCLUDE_ANY) {
|
||||||
if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
|
if(((shader & SHADER_EXCLUDE_DIFFUSE) && (state->flag & PATH_RAY_DIFFUSE)) ||
|
||||||
((shader & SHADER_EXCLUDE_GLOSSY) &&
|
((shader & SHADER_EXCLUDE_GLOSSY) &&
|
||||||
@ -305,20 +306,27 @@ ccl_device_noinline float3 indirect_background(KernelGlobals *kg,
|
|||||||
return make_float3(0.0f, 0.0f, 0.0f);
|
return make_float3(0.0f, 0.0f, 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* evaluate background closure */
|
|
||||||
|
/* Evaluate background shader. */
|
||||||
|
float3 L;
|
||||||
|
if(!shader_constant_emission_eval(kg, shader, &L)) {
|
||||||
# ifdef __SPLIT_KERNEL__
|
# ifdef __SPLIT_KERNEL__
|
||||||
Ray priv_ray = *ray;
|
Ray priv_ray = *ray;
|
||||||
shader_setup_from_background(kg, emission_sd, &priv_ray);
|
shader_setup_from_background(kg, emission_sd, &priv_ray);
|
||||||
# else
|
# else
|
||||||
shader_setup_from_background(kg, emission_sd, ray);
|
shader_setup_from_background(kg, emission_sd, ray);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
path_state_modify_bounce(state, true);
|
path_state_modify_bounce(state, true);
|
||||||
float3 L = shader_eval_background(kg, emission_sd, state, state->flag);
|
shader_eval_surface(kg, emission_sd, state, PATH_RAY_EMISSION);
|
||||||
path_state_modify_bounce(state, false);
|
path_state_modify_bounce(state, false);
|
||||||
|
|
||||||
|
L = shader_background_eval(emission_sd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Background MIS weights. */
|
||||||
#ifdef __BACKGROUND_MIS__
|
#ifdef __BACKGROUND_MIS__
|
||||||
/* check if background light exists or if we should skip pdf */
|
/* Check if background light exists or if we should skip pdf. */
|
||||||
int res_x = kernel_data.integrator.pdf_background_res_x;
|
int res_x = kernel_data.integrator.pdf_background_res_x;
|
||||||
|
|
||||||
if(!(state->flag & PATH_RAY_MIS_SKIP) && res_x) {
|
if(!(state->flag & PATH_RAY_MIS_SKIP) && res_x) {
|
||||||
|
@ -984,9 +984,40 @@ ccl_device float3 shader_bssrdf_sum(ShaderData *sd, float3 *N_, float *texture_b
|
|||||||
}
|
}
|
||||||
#endif /* __SUBSURFACE__ */
|
#endif /* __SUBSURFACE__ */
|
||||||
|
|
||||||
|
/* Constant emission optimization */
|
||||||
|
|
||||||
|
ccl_device bool shader_constant_emission_eval(KernelGlobals *kg, int shader, float3 *eval)
|
||||||
|
{
|
||||||
|
int shader_index = shader & SHADER_MASK;
|
||||||
|
int shader_flag = kernel_tex_fetch(__shaders, shader_index).flags;
|
||||||
|
|
||||||
|
if (shader_flag & SD_HAS_CONSTANT_EMISSION) {
|
||||||
|
*eval = make_float3(
|
||||||
|
kernel_tex_fetch(__shaders, shader_index).constant_emission[0],
|
||||||
|
kernel_tex_fetch(__shaders, shader_index).constant_emission[1],
|
||||||
|
kernel_tex_fetch(__shaders, shader_index).constant_emission[2]);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Background */
|
||||||
|
|
||||||
|
ccl_device float3 shader_background_eval(ShaderData *sd)
|
||||||
|
{
|
||||||
|
if(sd->flag & SD_EMISSION) {
|
||||||
|
return sd->closure_emission_background;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return make_float3(0.0f, 0.0f, 0.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Emission */
|
/* Emission */
|
||||||
|
|
||||||
ccl_device float3 shader_emissive_eval(KernelGlobals *kg, ShaderData *sd)
|
ccl_device float3 shader_emissive_eval(ShaderData *sd)
|
||||||
{
|
{
|
||||||
if(sd->flag & SD_EMISSION) {
|
if(sd->flag & SD_EMISSION) {
|
||||||
return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background;
|
return emissive_simple_eval(sd->Ng, sd->I) * sd->closure_emission_background;
|
||||||
@ -1034,20 +1065,32 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
|||||||
sd->num_closure_left = max_closures;
|
sd->num_closure_left = max_closures;
|
||||||
|
|
||||||
#ifdef __OSL__
|
#ifdef __OSL__
|
||||||
if(kg->osl)
|
if(kg->osl) {
|
||||||
OSLShader::eval_surface(kg, sd, state, path_flag);
|
if (sd->object == OBJECT_NONE) {
|
||||||
|
OSLShader::eval_background(kg, sd, state, path_flag);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
OSLShader::eval_surface(kg, sd, state, path_flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef __SVM__
|
#ifdef __SVM__
|
||||||
svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
|
svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
|
||||||
#else
|
#else
|
||||||
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd,
|
if(sd->object == OBJECT_NONE) {
|
||||||
sizeof(DiffuseBsdf),
|
sd->closure_emission_background = make_float3(0.8f, 0.8f, 0.8f);
|
||||||
make_float3(0.8f, 0.8f, 0.8f));
|
sd->flag |= SD_EMISSION;
|
||||||
if(bsdf != NULL) {
|
}
|
||||||
bsdf->N = sd->N;
|
else {
|
||||||
sd->flag |= bsdf_diffuse_setup(bsdf);
|
DiffuseBsdf *bsdf = (DiffuseBsdf*)bsdf_alloc(sd,
|
||||||
|
sizeof(DiffuseBsdf),
|
||||||
|
make_float3(0.8f, 0.8f, 0.8f));
|
||||||
|
if(bsdf != NULL) {
|
||||||
|
bsdf->N = sd->N;
|
||||||
|
sd->flag |= bsdf_diffuse_setup(bsdf);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -1057,36 +1100,6 @@ ccl_device void shader_eval_surface(KernelGlobals *kg, ShaderData *sd,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Background Evaluation */
|
|
||||||
|
|
||||||
ccl_device float3 shader_eval_background(KernelGlobals *kg, ShaderData *sd,
|
|
||||||
ccl_addr_space PathState *state, int path_flag)
|
|
||||||
{
|
|
||||||
sd->num_closure = 0;
|
|
||||||
sd->num_closure_left = 0;
|
|
||||||
|
|
||||||
#ifdef __SVM__
|
|
||||||
# ifdef __OSL__
|
|
||||||
if(kg->osl) {
|
|
||||||
OSLShader::eval_background(kg, sd, state, path_flag);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
# endif /* __OSL__ */
|
|
||||||
{
|
|
||||||
svm_eval_nodes(kg, sd, state, SHADER_TYPE_SURFACE, path_flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(sd->flag & SD_EMISSION) {
|
|
||||||
return sd->closure_emission_background;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return make_float3(0.0f, 0.0f, 0.0f);
|
|
||||||
}
|
|
||||||
#else /* __SVM__ */
|
|
||||||
return make_float3(0.8f, 0.8f, 0.8f);
|
|
||||||
#endif /* __SVM__ */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Volume */
|
/* Volume */
|
||||||
|
|
||||||
#ifdef __VOLUME__
|
#ifdef __VOLUME__
|
||||||
|
@ -219,21 +219,38 @@ bool Shader::is_constant_emission(float3 *emission)
|
|||||||
{
|
{
|
||||||
ShaderInput *surf = graph->output()->input("Surface");
|
ShaderInput *surf = graph->output()->input("Surface");
|
||||||
|
|
||||||
if(!surf->link || surf->link->parent->type != EmissionNode::node_type) {
|
if(surf->link == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EmissionNode *node = (EmissionNode*) surf->link->parent;
|
if(surf->link->parent->type == EmissionNode::node_type) {
|
||||||
|
EmissionNode *node = (EmissionNode*) surf->link->parent;
|
||||||
|
|
||||||
assert(node->input("Color"));
|
assert(node->input("Color"));
|
||||||
assert(node->input("Strength"));
|
assert(node->input("Strength"));
|
||||||
|
|
||||||
if(node->input("Color")->link || node->input("Strength")->link) {
|
if(node->input("Color")->link || node->input("Strength")->link) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*emission = node->color*node->strength;
|
||||||
|
}
|
||||||
|
else if(surf->link->parent->type == BackgroundNode::node_type) {
|
||||||
|
BackgroundNode *node = (BackgroundNode*) surf->link->parent;
|
||||||
|
|
||||||
|
assert(node->input("Color"));
|
||||||
|
assert(node->input("Strength"));
|
||||||
|
|
||||||
|
if(node->input("Color")->link || node->input("Strength")->link) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
*emission = node->color*node->strength;
|
||||||
|
}
|
||||||
|
else {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*emission = node->color*node->strength;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user