case nir_intrinsic_memory_barrier_shared:
       emit_memory_barrier(ctx, instr);
       break;
+   case nir_intrinsic_memory_barrier_tcs_patch:
+      break;
    case nir_intrinsic_load_num_work_groups: {
       Temp dst = get_ssa_temp(ctx, &instr->dest.ssa);
       bld.copy(Definition(dst), Operand(get_arg(ctx, ctx->args->ac.num_work_groups)));
 
        case nir_intrinsic_memory_barrier_shared:
                emit_membar(&ctx->ac, instr);
                break;
+       case nir_intrinsic_memory_barrier_tcs_patch:
+               break;
        case nir_intrinsic_barrier:
                ac_emit_barrier(&ctx->ac, ctx->stage);
                break;
 
         case nir_intrinsic_memory_barrier_buffer:
         case nir_intrinsic_memory_barrier_image:
         case nir_intrinsic_memory_barrier_shared:
+        case nir_intrinsic_memory_barrier_tcs_patch:
         case nir_intrinsic_group_memory_barrier:
                 /* We don't do any instruction scheduling of these NIR
                  * instructions between each other, so we just need to make
 
 barrier("begin_invocation_interlock")
 barrier("end_invocation_interlock")
 
+# Memory barrier for synchronizing TCS patch outputs
+barrier("memory_barrier_tcs_patch")
+
 # A conditional discard/demote, with a single boolean source.
 intrinsic("discard_if", src_comp=[1])
 intrinsic("demote_if", src_comp=[1])
 
          combine_stores_with_modes(state, nir_var_mem_shared);
          break;
 
+      case nir_intrinsic_memory_barrier_tcs_patch:
+         combine_stores_with_modes(state, nir_var_shader_out);
+         break;
+
       case nir_intrinsic_scoped_memory_barrier:
          if (nir_intrinsic_memory_semantics(intrin) & NIR_MEMORY_RELEASE) {
             combine_stores_with_modes(state,
 
          apply_barrier_for_modes(copies, nir_var_mem_shared);
          break;
 
+      case nir_intrinsic_memory_barrier_tcs_patch:
+         if (debug) dump_instr(instr);
+
+         apply_barrier_for_modes(copies, nir_var_shader_out);
+         break;
+
       case nir_intrinsic_scoped_memory_barrier:
          if (debug) dump_instr(instr);
 
 
          clear_unused_for_modes(&unused_writes, nir_var_mem_shared);
          break;
 
+      case nir_intrinsic_memory_barrier_tcs_patch:
+         clear_unused_for_modes(&unused_writes, nir_var_shader_out);
+         break;
+
       case nir_intrinsic_scoped_memory_barrier: {
          if (nir_intrinsic_memory_semantics(intrin) & NIR_MEMORY_RELEASE) {
             clear_unused_for_modes(&unused_writes,
 
                        break;
 
                case nir_intrinsic_barrier:
+               case nir_intrinsic_memory_barrier_tcs_patch:
                        /* Hull shaders dispatch 32 wide so an entire patch will always
                         * fit in a single warp and execute in lock-step.  Consequently,
                         * we don't need to do anything for TCS barriers so just remove
 
    case nir_intrinsic_memory_barrier_shared:
    case nir_intrinsic_memory_barrier_buffer:
    case nir_intrinsic_memory_barrier_image:
+   case nir_intrinsic_memory_barrier_tcs_patch:
       break;
    case nir_intrinsic_load_kernel_input:
       visit_load_kernel_input(bld_base, instr, result);
 
       bar->subOp = getSubOp(op);
       break;
    }
+   case nir_intrinsic_memory_barrier_tcs_patch:
+      break;
    case nir_intrinsic_shader_clock: {
       const DataType dType = getDType(insn);
       LValues &newDefs = convert(&insn->dest);
 
       break;
    }
 
+   case nir_intrinsic_memory_barrier_tcs_patch:
+      break;
+
    case nir_intrinsic_shader_clock: {
       /* We cannot do anything if there is an event, so ignore it for now */
       const fs_reg shader_clock = get_timestamp(bld);
 
       break;
    }
 
+   case nir_intrinsic_memory_barrier_tcs_patch:
+      break;
+
    default:
       vec4_visitor::nir_emit_intrinsic(instr);
    }