+ op = &metrics->op_metrics[i];
+
+ /* Accumulate total time across all ops. */
+ total_time += op->time_ns;
+
+ /* Also, find total cycles in all stages of this op. */
+ op_cycles = 0.0;
+
+ if (num_shader_stages == 0) {
+ per_stage = &sorted[i];
+ per_stage->metrics = op;
+ per_stage->stage = NULL;
+ per_stage->time_ns = op->time_ns;
+ per_stage->active = 0.0;
+ }
+
+ for (j = 0; j < num_shader_stages; j++) {
+ /* Active cycles */
+ group_index = info->stages[j].active_group_index;
+ counter_index = info->stages[j].active_counter_index;
+ op_cycles += op->counters[group_index][counter_index];
+
+ /* Stall cycles */
+ group_index = info->stages[j].stall_group_index;
+ counter_index = info->stages[j].stall_counter_index;
+ op_cycles += op->counters[group_index][counter_index];
+ }
+
+ for (j = 0; j < num_shader_stages; j++) {
+ double active_cycles, stall_cycles, stage_cycles;
+
+ /* Active cycles */
+ group_index = info->stages[j].active_group_index;
+ counter_index = info->stages[j].active_counter_index;
+ active_cycles = op->counters[group_index][counter_index];
+
+ /* Stall cycles */
+ group_index = info->stages[j].stall_group_index;
+ counter_index = info->stages[j].stall_counter_index;
+ stall_cycles = op->counters[group_index][counter_index];
+
+ stage_cycles = active_cycles + stall_cycles;
+
+ per_stage = &sorted[i * num_shader_stages + j];
+ per_stage->metrics = op;
+
+ if (op_cycles) {
+ per_stage->stage = &info->stages[j];
+ per_stage->time_ns = op->time_ns * (stage_cycles / op_cycles);
+ } else {
+ /* If we don't have any per-stage cycle counts
+ * for this operation, then use the first
+ * stage as a placeholder for all the time,
+ * but NULL-ify the stage info so that the
+ * report doesn't lie about this time being
+ * from any particular stage. */
+ per_stage->stage = NULL;
+ if (j == 0) {
+ per_stage->time_ns = op->time_ns;
+ } else {
+ per_stage->time_ns = 0.0;
+ }
+ }
+
+ if (stage_cycles) {
+ per_stage->active = active_cycles / stage_cycles;
+ } else {
+ per_stage->active = 0.0;
+ }
+ }