radv/rt: Miss rays that hit the triangle's v edge

The hardware seems to do this as well. Avoids invoking hit shaders twice
at shared edges.
Fixes the fails in watertightness tests on emulated RT.

Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24063>
This commit is contained in:
Friedrich Vock 2023-07-09 21:12:00 +02:00 committed by Marge Bot
parent a096cf784f
commit e034ba1c44

View file

@ -253,40 +253,6 @@ intersect_ray_amd_software_tri(struct radv_device *device, nir_builder *b, nir_s
nir_ssa_def *v = nir_fsub(b, nir_fmul(b, ax, cy), nir_fmul(b, ay, cx));
nir_ssa_def *w = nir_fsub(b, nir_fmul(b, bx, ay), nir_fmul(b, by, ax));
nir_variable *u_var = nir_variable_create(b->shader, nir_var_shader_temp, glsl_float_type(), "u");
nir_variable *v_var = nir_variable_create(b->shader, nir_var_shader_temp, glsl_float_type(), "v");
nir_variable *w_var = nir_variable_create(b->shader, nir_var_shader_temp, glsl_float_type(), "w");
nir_store_var(b, u_var, u, 0x1);
nir_store_var(b, v_var, v, 0x1);
nir_store_var(b, w_var, w, 0x1);
/* Fallback to testing edges with double precision...
*
* The Vulkan spec states it only needs single precision watertightness
* but we fail dEQP-VK.ray_tracing_pipeline.watertightness.closedFan2.1024 with
* failures = 1 without doing this. :( */
nir_ssa_def *cond_retest =
nir_ior(b, nir_ior(b, nir_feq_imm(b, u, 0.0f), nir_feq_imm(b, v, 0.0f)), nir_feq_imm(b, w, 0.0f));
nir_push_if(b, cond_retest);
{
ax = nir_f2f64(b, ax);
ay = nir_f2f64(b, ay);
bx = nir_f2f64(b, bx);
by = nir_f2f64(b, by);
cx = nir_f2f64(b, cx);
cy = nir_f2f64(b, cy);
nir_store_var(b, u_var, nir_f2f32(b, nir_fsub(b, nir_fmul(b, cx, by), nir_fmul(b, cy, bx))), 0x1);
nir_store_var(b, v_var, nir_f2f32(b, nir_fsub(b, nir_fmul(b, ax, cy), nir_fmul(b, ay, cx))), 0x1);
nir_store_var(b, w_var, nir_f2f32(b, nir_fsub(b, nir_fmul(b, bx, ay), nir_fmul(b, by, ax))), 0x1);
}
nir_pop_if(b, NULL);
u = nir_load_var(b, u_var);
v = nir_load_var(b, v_var);
w = nir_load_var(b, w_var);
/* Perform edge tests. */
nir_ssa_def *cond_back =
nir_ior(b, nir_ior(b, nir_flt_imm(b, u, 0.0f), nir_flt_imm(b, v, 0.0f)), nir_flt_imm(b, w, 0.0f));
@ -296,6 +262,13 @@ intersect_ray_amd_software_tri(struct radv_device *device, nir_builder *b, nir_s
nir_ssa_def *cond = nir_inot(b, nir_iand(b, cond_back, cond_front));
/* If the ray is exactly on the edge where v is 0, consider it a miss.
* This seems to correspond to what the hardware is doing.
* Also, it avoids invoking hit shaders twice on a shared edge, which is
* discouraged by the spec.
*/
cond = nir_iand(b, cond, nir_fneu(b, v, nir_imm_float(b, 0.0f)));
nir_push_if(b, cond);
{
nir_ssa_def *det = nir_fadd(b, u, nir_fadd(b, v, w));