From e034ba1c44ac662699026bdadfa68af61bb6c1be Mon Sep 17 00:00:00 2001 From: Friedrich Vock Date: Sun, 9 Jul 2023 21:12:00 +0200 Subject: [PATCH] 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: --- src/amd/vulkan/radv_rt_common.c | 41 +++++++---------------------------------- 1 file changed, 7 insertions(+), 34 deletions(-) diff --git a/src/amd/vulkan/radv_rt_common.c b/src/amd/vulkan/radv_rt_common.c index 75a9ea7..3e94c93 100644 --- a/src/amd/vulkan/radv_rt_common.c +++ b/src/amd/vulkan/radv_rt_common.c @@ -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)); -- 2.7.4