+#if GEN_GEN >= 8
+ case VK_QUERY_TYPE_PERFORMANCE_QUERY_KHR: {
+ anv_batch_emit(&cmd_buffer->batch, GENX(PIPE_CONTROL), pc) {
+ pc.CommandStreamerStallEnable = true;
+ pc.StallAtPixelScoreboard = true;
+ }
+
+ /* We know the bottom bits of the address are 0s which match what we
+ * want in the MI_RPC/MI_SDI packets.
+ */
+ struct gen_mi_value mi_rpc_write_offset =
+ gen_mi_iadd(
+ &b,
+ gen_mi_imm(
+ gen_canonical_address(
+ pool->bo->offset +
+ khr_perf_query_oa_offset(pool, query, 0 /* pass*/, true))),
+ gen_mi_reg64(ANV_PERF_QUERY_OFFSET_REG));
+ struct gen_mi_value availability_write_offset =
+ gen_mi_iadd(
+ &b,
+ gen_mi_imm(
+ gen_canonical_address(
+ pool->bo->offset +
+ khr_perf_query_availability_offset(pool, query, 0 /* pass */))),
+ gen_mi_reg64(ANV_PERF_QUERY_OFFSET_REG));
+
+ struct gen_mi_address_token mi_rpc_addr_dest =
+ gen_mi_store_address(&b, mi_rpc_write_offset);
+ struct gen_mi_address_token availability_addr_dest =
+ gen_mi_store_address(&b, availability_write_offset);
+ gen_mi_self_mod_barrier(&b);
+
+ void *mi_rpc_dws =
+ anv_batch_emitn(&cmd_buffer->batch,
+ GENX(MI_REPORT_PERF_COUNT_length),
+ GENX(MI_REPORT_PERF_COUNT),
+ .MemoryAddress = query_addr /* Will be overwritten */ );
+ _gen_mi_resolve_address_token(&b, mi_rpc_addr_dest,
+ mi_rpc_dws +
+ GENX(MI_REPORT_PERF_COUNT_MemoryAddress_start) / 8);
+
+ void *availability_dws =
+ anv_batch_emitn(&cmd_buffer->batch,
+ GENX(MI_STORE_DATA_IMM_length),
+ GENX(MI_STORE_DATA_IMM),
+ .ImmediateData = true);
+ _gen_mi_resolve_address_token(&b, availability_addr_dest,
+ availability_dws +
+ GENX(MI_STORE_DATA_IMM_Address_start) / 8);
+ break;
+ }
+#endif
+