freedreno/ir3: Implement TCS synchronization intrinsics
authorKristian H. Kristensen <hoegsberg@google.com>
Wed, 23 Oct 2019 02:30:51 +0000 (19:30 -0700)
committerKristian H. Kristensen <hoegsberg@google.com>
Fri, 8 Nov 2019 00:40:27 +0000 (16:40 -0800)
We add two new IR3 specific nir intrinsics that map to the new condend
and endpatch instructions.

Signed-off-by: Kristian H. Kristensen <hoegsberg@google.com>
Acked-by: Eric Anholt <eric@anholt.net>
Reviewed-by: Rob Clark <robdclark@gmail.com>
src/compiler/nir/nir_intrinsics.py
src/freedreno/ir3/ir3_compiler_nir.c

index 55050a9e0583d17597eb1405b2611bd9e7cc01cd..4658187ea16907fd0358042fa243414c44791ac7 100644 (file)
@@ -798,6 +798,14 @@ system_value("tess_factor_base_ir3", 2)
 system_value("tess_param_base_ir3", 2)
 system_value("tcs_header_ir3", 1)
 
+# IR3-specific intrinsics for tessellation control shaders.  cond_end_ir3 end
+# the shader when src0 is false and is used to narrow down the TCS shader to
+# just thread 0 before writing out tessellation levels.
+intrinsic("cond_end_ir3", src_comp=[1])
+# end_patch_ir3 is used just before thread 0 exist the TCS and presumably
+# signals the TE that the patch is complete and can be tessellated.
+intrinsic("end_patch_ir3")
+
 # IR3-specific load/store intrinsics. These access a buffer used to pass data
 # between geometry stages - perhaps it's explicit access to the vertex cache.
 
index b2068a354667f2ab4ba2702415b5543faafb3b82..2341c359324e9178181c9043f1a9103f0473b428 100644 (file)
@@ -1406,6 +1406,15 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
                dst[2] = create_immed(b, 0);
                break;
 
+       case nir_intrinsic_end_patch_ir3:
+               assert(ctx->so->type == MESA_SHADER_TESS_CTRL);
+               struct ir3_instruction *end = ir3_ENDPATCH(b);
+               array_insert(b, b->keeps, end);
+
+               end->barrier_class = IR3_BARRIER_EVERYTHING;
+               end->barrier_conflict = IR3_BARRIER_EVERYTHING;
+               break;
+
        case nir_intrinsic_store_global_ir3: {
                struct ir3_instruction *value, *addr, *offset;
 
@@ -1762,6 +1771,30 @@ emit_intrinsic(struct ir3_context *ctx, nir_intrinsic_instr *intr)
 
                break;
        }
+
+       case nir_intrinsic_cond_end_ir3: {
+               struct ir3_instruction *cond, *kill;
+
+               src = ir3_get_src(ctx, &intr->src[0]);
+               cond = ir3_b2n(b, src[0]);
+
+               /* NOTE: only cmps.*.* can write p0.x: */
+               cond = ir3_CMPS_S(b, cond, 0, create_immed(b, 0), 0);
+               cond->cat2.condition = IR3_COND_NE;
+
+               /* condition always goes in predicate register: */
+               cond->regs[0]->num = regid(REG_P0, 0);
+
+               kill = ir3_CONDEND(b, cond, 0);
+
+               kill->barrier_class = IR3_BARRIER_EVERYTHING;
+               kill->barrier_conflict = IR3_BARRIER_EVERYTHING;
+
+               array_insert(ctx->ir, ctx->ir->predicates, kill);
+               array_insert(b, b->keeps, kill);
+               break;
+       }
+
        case nir_intrinsic_load_shared_ir3:
                emit_intrinsic_load_shared_ir3(ctx, intr, dst);
                break;