EEVEE-Next: Limit cost of transmission evaluation

This uses specialization constants to compile
optimized deferred lighting shader for when
transmission is not needed.
This commit is contained in:
Clément Foucault
2024-05-10 20:01:22 +02:00
parent 717f546f91
commit bbde7cdcb6
3 changed files with 18 additions and 15 deletions

View File

@@ -617,6 +617,7 @@ void DeferredLayer::end_sync(bool is_first_pass, bool is_last_pass)
sub.barrier(GPU_BARRIER_SHADER_IMAGE_ACCESS);
}
{
const bool use_transmission = (closure_bits_ & CLOSURE_TRANSMISSION) != 0;
const bool use_split_indirect = !use_raytracing_ && use_split_radiance_;
PassSimple::Sub &sub = pass.sub("Eval.Light");
/* Use depth test to reject background pixels which have not been stencil cleared. */
@@ -636,6 +637,7 @@ void DeferredLayer::end_sync(bool is_first_pass, bool is_last_pass)
sub.specialize_constant(sh, "render_pass_shadow_id", rbuf_data.shadow_id);
sub.specialize_constant(sh, "use_split_indirect", use_split_indirect);
sub.specialize_constant(sh, "use_lightprobe_eval", !use_raytracing_);
sub.specialize_constant(sh, "use_transmission", false);
const ShadowSceneData &shadow_scene = inst_.shadows.get_data();
sub.specialize_constant(sh, "shadow_ray_count", &shadow_scene.ray_count);
sub.specialize_constant(sh, "shadow_ray_step_count", &shadow_scene.step_count);
@@ -654,11 +656,18 @@ void DeferredLayer::end_sync(bool is_first_pass, bool is_last_pass)
sub.bind_resources(inst_.hiz_buffer.front);
sub.bind_resources(inst_.sphere_probes);
sub.bind_resources(inst_.volume_probes);
/* TODO(fclem): Transmission evaluation specialization. */
uint8_t compare_mask = uint8_t(StencilBits::CLOSURE_COUNT_0) |
uint8_t(StencilBits::CLOSURE_COUNT_1);
uint8_t(StencilBits::CLOSURE_COUNT_1) |
uint8_t(StencilBits::TRANSMISSION);
sub.state_stencil(0x0u, i + 1, compare_mask);
sub.draw_procedural(GPU_PRIM_TRIS, 1, 3);
if (use_transmission) {
/* Separate pass for transmission BSDF as their evaluation is quite costly. */
sub.specialize_constant(sh, "use_transmission", true);
sub.shader_set(sh);
sub.state_stencil(0x0u, (i + 1) | uint8_t(StencilBits::TRANSMISSION), compare_mask);
sub.draw_procedural(GPU_PRIM_TRIS, 1, 3);
}
}
}
}

View File

@@ -70,28 +70,22 @@ void main()
* by 1 for this evaluation and skip evaluating the transmission closure twice. */
light_eval_reflection(stack, P, Ng, V, vPz);
#if 1 /* TODO Limit to transmission. Can bypass the check if stencil is tagged properly and use \
specialization constant. */
ClosureUndetermined cl_transmit = gbuffer_closure_get(gbuf, 0);
if ((cl_transmit.type == CLOSURE_BSDF_TRANSLUCENT_ID) ||
(cl_transmit.type == CLOSURE_BSDF_MICROFACET_GGX_REFRACTION_ID) ||
(cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID))
{
# if 1 /* TODO Limit to SSS. */
if (use_transmission) {
ClosureUndetermined cl_transmit = gbuffer_closure_get(gbuf, 0);
#if 1 /* TODO Limit to SSS. */
vec3 sss_reflect_shadowed, sss_reflect_unshadowed;
if (cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID) {
sss_reflect_shadowed = stack.cl[0].light_shadowed;
sss_reflect_unshadowed = stack.cl[0].light_unshadowed;
}
# endif
#endif
stack.cl[0] = closure_light_new(cl_transmit, V, gbuf.thickness);
/* NOTE: Only evaluates `stack.cl[0]`. */
light_eval_transmission(stack, P, Ng, V, vPz, gbuf.thickness);
# if 1 /* TODO Limit to SSS. */
#if 1 /* TODO Limit to SSS. */
if (cl_transmit.type == CLOSURE_BSSRDF_BURLEY_ID) {
/* Apply transmission profile onto transmitted light and sum with reflected light. */
vec3 sss_profile = subsurface_transmission(to_closure_subsurface(cl_transmit).sss_radius,
@@ -101,9 +95,8 @@ void main()
stack.cl[0].light_shadowed += sss_reflect_shadowed;
stack.cl[0].light_unshadowed += sss_reflect_unshadowed;
}
# endif
}
#endif
}
if (render_pass_shadow_id != -1) {
vec3 radiance_shadowed = vec3(0);

View File

@@ -63,6 +63,7 @@ GPU_SHADER_CREATE_INFO(eevee_deferred_light)
.image_out(7, DEFERRED_RADIANCE_FORMAT, "indirect_radiance_3_img")
.specialization_constant(Type::BOOL, "use_split_indirect", false)
.specialization_constant(Type::BOOL, "use_lightprobe_eval", false)
.specialization_constant(Type::BOOL, "use_transmission", false)
.specialization_constant(Type::INT, "render_pass_shadow_id", -1)
.define("SPECIALIZED_SHADOW_PARAMS")
.specialization_constant(Type::INT, "shadow_ray_count", 1)