From b517255ec85f4a13d6834415e783ad4501d10132 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: (cherry picked from commit e034ba1c44ac662699026bdadfa68af61bb6c1be) --- .pick_status.json | 2 +- src/amd/vulkan/radv_rt_common.c | 48 +++++---------------------------- 2 files changed, 8 insertions(+), 42 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index b21921cc46c..614824f3c1f 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -1993,7 +1993,7 @@ "description": "radv/rt: Miss rays that hit the triangle's v edge", "nominated": true, "nomination_type": 0, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": null }, diff --git a/src/amd/vulkan/radv_rt_common.c b/src/amd/vulkan/radv_rt_common.c index 456577cfaa7..0b2508a4ea0 100644 --- a/src/amd/vulkan/radv_rt_common.c +++ b/src/amd/vulkan/radv_rt_common.c @@ -282,47 +282,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(b, u, nir_imm_float(b, 0.0f)), nir_feq(b, v, nir_imm_float(b, 0.0f))), - nir_feq(b, w, nir_imm_float(b, 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(b, u, nir_imm_float(b, 0.0f)), nir_flt(b, v, nir_imm_float(b, 0.0f))), @@ -334,6 +293,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));