r300/compiler: Use the smart scheduler for r300 cards
authorTom Stellard <tstellar@gmail.com>
Tue, 14 Feb 2012 02:26:15 +0000 (21:26 -0500)
committerTom Stellard <tstellar@gmail.com>
Sun, 26 Feb 2012 20:13:40 +0000 (15:13 -0500)
src/gallium/drivers/r300/compiler/radeon_pair_schedule.c

index fa2e80f..d230206 100644 (file)
@@ -298,9 +298,53 @@ static void calc_score_deps(struct schedule_instruction * sinst)
 
 #endif
 
-#define NO_READ_TEX_SCORE (1 << 16)
 #define NO_OUTPUT_SCORE (1 << 24)
 
+static void score_no_output(struct schedule_instruction * sinst)
+{
+       assert(sinst->Instruction->Type != RC_INSTRUCTION_NORMAL);
+       if (!sinst->Instruction->U.P.RGB.OutputWriteMask &&
+                       !sinst->Instruction->U.P.Alpha.OutputWriteMask) {
+               if (sinst->PairedInst) {
+                       if (!sinst->PairedInst->Instruction->U.P.
+                                                       RGB.OutputWriteMask
+                                       && !sinst->PairedInst->Instruction->U.P.
+                                                       Alpha.OutputWriteMask) {
+                               sinst->Score |= NO_OUTPUT_SCORE;
+                       }
+
+               } else {
+                       sinst->Score |= NO_OUTPUT_SCORE;
+               }
+       }
+}
+
+#define PAIRED_SCORE (1 << 16)
+
+static void calc_score_r300(struct schedule_instruction * sinst)
+{
+       unsigned src_idx;
+
+       if (sinst->Instruction->Type == RC_INSTRUCTION_NORMAL) {
+               sinst->Score = 0;
+               return;
+       }
+
+       score_no_output(sinst);
+
+       if (sinst->PairedInst) {
+               sinst->Score |= PAIRED_SCORE;
+               return;
+       }
+
+       for (src_idx = 0; src_idx < 4; src_idx++) {
+               sinst->Score += sinst->Instruction->U.P.RGB.Src[src_idx].Used +
+                               sinst->Instruction->U.P.Alpha.Src[src_idx].Used;
+       }
+}
+
+#define NO_READ_TEX_SCORE (1 << 16)
+
 static void calc_score_readers(struct schedule_instruction * sinst)
 {
        if (sinst->Instruction->Type == RC_INSTRUCTION_NORMAL) {
@@ -313,20 +357,7 @@ static void calc_score_readers(struct schedule_instruction * sinst)
                if (get_tex_read_count(sinst) == 0) {
                        sinst->Score |= NO_READ_TEX_SCORE;
                }
-               if (!sinst->Instruction->U.P.RGB.OutputWriteMask &&
-                       !sinst->Instruction->U.P.Alpha.OutputWriteMask) {
-                       if (sinst->PairedInst) {
-                               if (!sinst->PairedInst->Instruction->U.P.
-                                               RGB.OutputWriteMask
-                               && !sinst->PairedInst->Instruction->U.P.
-                                               Alpha.OutputWriteMask) {
-                                       sinst->Score |= NO_OUTPUT_SCORE;
-                               }
-
-                       } else {
-                               sinst->Score |= NO_OUTPUT_SCORE;
-                       }
-               }
+               score_no_output(sinst);
        }
 }
 
@@ -1080,7 +1111,8 @@ static void emit_instruction(
        update_max_score(s, &s->ReadyAlpha, &max_score, &max_inst, &max_list);
 
        if (tex_count >= s->max_tex_group || max_score == -1
-               || (s->TEXCount > 0 && tex_count == s->TEXCount)) {
+               || (s->TEXCount > 0 && tex_count == s->TEXCount)
+               || (!s->C->is_r500 && tex_count > 0 && max_score == -1)) {
                emit_all_tex(s, before);
        } else {
 
@@ -1093,53 +1125,6 @@ static void emit_instruction(
        }
 }
 
-/**
- * Find a good ALU instruction or pair of ALU instruction and emit it.
- *
- * Prefer emitting full ALU instructions, so that when we reach a point
- * where no full ALU instruction can be emitted, we have more candidates
- * for RGB/Alpha pairing.
- */
-static void emit_one_alu(struct schedule_state *s, struct rc_instruction * before)
-{
-       struct schedule_instruction * sinst;
-       int rgb_score = -1, alpha_score = -1;
-
-       /* Try to merge RGB and Alpha instructions together. */
-       pair_instructions(s);
-
-       if (s->ReadyFullALU) {
-               sinst = s->ReadyFullALU;
-               s->ReadyFullALU = s->ReadyFullALU->NextReady;
-               rc_insert_instruction(before->Prev, sinst->Instruction);
-               commit_alu_instruction(s, sinst);
-       } else {
-               if (s->ReadyRGB) {
-                       rgb_score = s->ReadyRGB->Score;
-               }
-               if (s->ReadyAlpha) {
-                       alpha_score = s->ReadyAlpha->Score;
-               }
-               if (rgb_score > alpha_score) {
-                       sinst = s->ReadyRGB;
-                       s->ReadyRGB = s->ReadyRGB->NextReady;
-               } else if (s->ReadyAlpha) {
-                       sinst = s->ReadyAlpha;
-                       s->ReadyAlpha = s->ReadyAlpha->NextReady;
-               } else {
-                       /*XXX Something real bad has happened. */
-                       assert(0);
-               }
-
-               rc_insert_instruction(before->Prev, sinst->Instruction);
-               commit_alu_instruction(s, sinst);
-       }
-       /* If the instruction we just emitted uses a presubtract value, and
-        * the presubtract sources were written by the previous intstruction,
-        * the previous instruction needs a nop. */
-       presub_nop(before->Prev);
-}
-
 static void add_tex_reader(
        struct schedule_state * s,
        struct schedule_instruction * writer,
@@ -1317,15 +1302,7 @@ static void schedule_block(struct schedule_state * s,
        /* Schedule instructions back */
        while(!s->C->Error &&
              (s->ReadyTEX || s->ReadyRGB || s->ReadyAlpha || s->ReadyFullALU)) {
-               if (s->C->is_r500) {
-                       emit_instruction(s, end);
-               } else {
-                       if (s->ReadyTEX)
-                               emit_all_tex(s, end);
-
-                       while(!s->C->Error && (s->ReadyFullALU || s->ReadyRGB || s->ReadyAlpha))
-                               emit_one_alu(s, end);
-               }
+               emit_instruction(s, end);
        }
 }
 
@@ -1348,7 +1325,11 @@ void rc_pair_schedule(struct radeon_compiler *cc, void *user)
        memset(&s, 0, sizeof(s));
        s.Opt = *opt;
        s.C = &c->Base;
-       s.CalcScore = calc_score_readers;
+       if (s.C->is_r500) {
+               s.CalcScore = calc_score_readers;
+       } else {
+               s.CalcScore = calc_score_r300;
+       }
        s.max_tex_group = debug_get_num_option("RADEON_TEX_GROUP", 8);
        while(inst != &c->Base.Program.Instructions) {
                struct rc_instruction * first;