From 2d45836c95dadb70324db9d94b105da5792ab126 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Fri, 15 Mar 2024 10:41:49 -0400 Subject: [PATCH] ir3: Plumb through ray_intersection intrinsic Part-of: --- src/compiler/nir/nir_divergence_analysis.c | 3 ++- src/compiler/nir/nir_intrinsics.py | 6 +++++ src/freedreno/ir3/ir3.h | 2 ++ src/freedreno/ir3/ir3_compiler_nir.c | 29 ++++++++++++++++++++++ src/freedreno/ir3/ir3_validate.c | 8 ++++++ 5 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 59796b7cd41..9727d46fa29 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -699,7 +699,8 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) case nir_intrinsic_load_const_ir3: case nir_intrinsic_load_frag_size_ir3: case nir_intrinsic_load_frag_offset_ir3: - case nir_intrinsic_bindless_resource_ir3: { + case nir_intrinsic_bindless_resource_ir3: + case nir_intrinsic_ray_intersection_ir3: { unsigned num_srcs = nir_intrinsic_infos[instr->intrinsic].num_srcs; for (unsigned i = 0; i < num_srcs; i++) { if (src_divergent(instr->src[i], state)) { diff --git a/src/compiler/nir/nir_intrinsics.py b/src/compiler/nir/nir_intrinsics.py index d0255752ba0..51ec07f404b 100644 --- a/src/compiler/nir/nir_intrinsics.py +++ b/src/compiler/nir/nir_intrinsics.py @@ -1363,6 +1363,12 @@ intrinsic("ssbo_atomic_swap_ir3", src_comp=[1, 1, 1, 1, 1], dest_comp=1, load("uav_ir3", [1, 2], indices=[ACCESS, ALIGN_MUL, ALIGN_OFFSET], flags=[CAN_ELIMINATE]) +# IR3 intrinsic for "ray_intersection" instruction. +# The input and output arguments are the same as the instruction. +# See https://gitlab.freedesktop.org/freedreno/freedreno/-/wikis/a7xx-ray-tracing +intrinsic("ray_intersection_ir3", src_comp=[2, 1, 8, 1], dest_comp=5, + flags=[CAN_REORDER, CAN_ELIMINATE]) + # System values for freedreno geometry shaders. system_value("vs_primitive_stride_ir3", 1) system_value("vs_vertex_stride_ir3", 1) diff --git a/src/freedreno/ir3/ir3.h b/src/freedreno/ir3/ir3.h index 9100108ecd8..24241fd4ea8 100644 --- a/src/freedreno/ir3/ir3.h +++ b/src/freedreno/ir3/ir3.h @@ -1192,6 +1192,7 @@ is_load(struct ir3_instruction *instr) case OPC_L2G: case OPC_LDLW: case OPC_LDLV: + case OPC_RAY_INTERSECTION: /* probably some others too.. */ return true; case OPC_LDC: @@ -3031,6 +3032,7 @@ INSTR4(ATOMIC_S_OR) INSTR4(ATOMIC_S_XOR) #endif INSTR4NODST(LDG_K) +INSTR5(RAY_INTERSECTION) /* cat7 instructions: */ INSTR0(BAR) diff --git a/src/freedreno/ir3/ir3_compiler_nir.c b/src/freedreno/ir3/ir3_compiler_nir.c index 6cf4dffde3b..5a223adb5d0 100644 --- a/src/freedreno/ir3/ir3_compiler_nir.c +++ b/src/freedreno/ir3/ir3_compiler_nir.c @@ -2609,6 +2609,32 @@ emit_shfl(struct ir3_context *ctx, nir_intrinsic_instr *intr) return shfl; } +static void +emit_ray_intersection(struct ir3_context *ctx, nir_intrinsic_instr *intr, + struct ir3_instruction **dst) +{ + struct ir3_builder *b = &ctx->build; + + struct ir3_instruction *bvh_base = + ir3_create_collect(b, ir3_get_src(ctx, &intr->src[0]), 2); + struct ir3_instruction *idx = ir3_get_src(ctx, &intr->src[1])[0]; + + struct ir3_instruction *ray_info = + ir3_create_collect(b, ir3_get_src(ctx, &intr->src[2]), 8); + struct ir3_instruction *flags = ir3_get_src(ctx, &intr->src[3])[0]; + + struct ir3_instruction *dst_init = + ir3_collect(b, NULL, NULL, NULL, create_immed(b, 0), NULL); + + struct ir3_instruction *ray_intersection = + ir3_RAY_INTERSECTION(b, bvh_base, 0, idx, 0, ray_info, 0, flags, 0, + dst_init, 0); + ray_intersection->dsts[0]->wrmask = MASK(5); + ir3_reg_tie(ray_intersection->dsts[0], ray_intersection->srcs[4]); + + ir3_split_dest(b, dst, ray_intersection, 0, 5); +} + static void setup_input(struct ir3_context *ctx, nir_intrinsic_instr *intr); static void setup_output(struct ir3_context *ctx, nir_intrinsic_instr *intr); @@ -3417,6 +3443,9 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr) case nir_intrinsic_shuffle_xor_uniform_ir3: dst[0] = emit_shfl(ctx, intr); break; + case nir_intrinsic_ray_intersection_ir3: + emit_ray_intersection(ctx, intr, dst); + break; default: ir3_context_error(ctx, "Unhandled intrinsic type: %s\n", nir_intrinsic_infos[intr->intrinsic].name); diff --git a/src/freedreno/ir3/ir3_validate.c b/src/freedreno/ir3/ir3_validate.c index b8ffdfe4e90..7568c1652a5 100644 --- a/src/freedreno/ir3/ir3_validate.c +++ b/src/freedreno/ir3/ir3_validate.c @@ -483,6 +483,14 @@ validate_instr(struct ir3_validate_ctx *ctx, struct ir3_instruction *instr) validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF)); validate_reg_size(ctx, instr->dsts[0], instr->cat6.type); break; + case OPC_RAY_INTERSECTION: + validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF)); + validate_assert(ctx, !(instr->srcs[1]->flags & IR3_REG_HALF)); + validate_assert(ctx, !(instr->srcs[2]->flags & IR3_REG_HALF)); + validate_assert(ctx, !(instr->srcs[3]->flags & IR3_REG_HALF)); + validate_assert(ctx, !(instr->srcs[4]->flags & IR3_REG_HALF)); + validate_assert(ctx, !(instr->dsts[0]->flags & IR3_REG_HALF)); + break; default: validate_reg_size(ctx, instr->dsts[0], instr->cat6.type); validate_assert(ctx, !(instr->srcs[0]->flags & IR3_REG_HALF));