i965: Use immediate float operands for some VS instructions.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_vs_emit.c
index 227261409c431e5278eb38c0baa98b9de1584977..e83c9bf1051b338346526d2d2bf7ab1a4b6ccf87 100644 (file)
 #include "brw_context.h"
 #include "brw_vs.h"
 
+/* Return the SrcReg index of the channels that can be immediate float operands
+ * instead of usage of PROGRAM_CONSTANT values through push/pull.
+ */
+static GLboolean
+brw_vs_arg_can_be_immediate(enum prog_opcode opcode, int arg)
+{
+   int opcode_array[] = {
+      [OPCODE_ADD] = 2,
+      [OPCODE_CMP] = 3,
+      [OPCODE_DP3] = 2,
+      [OPCODE_DP4] = 2,
+      [OPCODE_DPH] = 2,
+      [OPCODE_MAX] = 1,
+      [OPCODE_MIN] = 2,
+      [OPCODE_MUL] = 2,
+      [OPCODE_SEQ] = 2,
+      [OPCODE_SGE] = 2,
+      [OPCODE_SGT] = 2,
+      [OPCODE_SLE] = 2,
+      [OPCODE_SLT] = 2,
+      [OPCODE_SNE] = 2,
+      [OPCODE_XPD] = 2,
+   };
+
+   /* These opcodes get broken down in a way that allow two
+    * args to be immediates.
+    */
+   if (opcode == OPCODE_MAD || opcode == OPCODE_LRP) {
+      if (arg == 1 || arg == 2)
+        return GL_TRUE;
+   }
+
+   if (opcode > ARRAY_SIZE(opcode_array))
+      return GL_FALSE;
+
+   return arg == opcode_array[opcode] - 1;
+}
 
 static struct brw_reg get_tmp( struct brw_vs_compile *c )
 {
@@ -182,7 +219,7 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
 
    if (intel->gen >= 6)
       mrf = 6;
-   else if (intel->is_ironlake)
+   else if (intel->gen == 5)
       mrf = 8;
    else
       mrf = 4;
@@ -283,7 +320,7 @@ static void brw_vs_alloc_regs( struct brw_vs_compile *c )
 
    if (intel->gen >= 6)
       c->prog_data.urb_entry_size = (attributes_in_vue + 4 + 7) / 8;
-   else if (intel->is_ironlake)
+   else if (intel->gen == 5)
       c->prog_data.urb_entry_size = (attributes_in_vue + 6 + 3) / 4;
    else
       c->prog_data.urb_entry_size = (attributes_in_vue + 2 + 3) / 4;
@@ -983,6 +1020,55 @@ get_src_reg( struct brw_vs_compile *c,
    const GLint index = inst->SrcReg[argIndex].Index;
    const GLboolean relAddr = inst->SrcReg[argIndex].RelAddr;
 
+   if (brw_vs_arg_can_be_immediate(inst->Opcode, argIndex)) {
+      const struct prog_src_register *src = &inst->SrcReg[argIndex];
+
+      if (src->Swizzle == MAKE_SWIZZLE4(SWIZZLE_ZERO,
+                                       SWIZZLE_ZERO,
+                                       SWIZZLE_ZERO,
+                                       SWIZZLE_ZERO)) {
+         return brw_imm_f(0.0f);
+      } else if (src->Swizzle == MAKE_SWIZZLE4(SWIZZLE_ONE,
+                                              SWIZZLE_ONE,
+                                              SWIZZLE_ONE,
+                                              SWIZZLE_ONE)) {
+        if (src->Negate)
+           return brw_imm_f(-1.0F);
+        else
+           return brw_imm_f(1.0F);
+      } else if (src->File == PROGRAM_CONSTANT) {
+        const struct gl_program_parameter_list *params;
+        float f;
+        int component = -1;
+
+        switch (src->Swizzle) {
+        case SWIZZLE_XXXX:
+           component = 0;
+           break;
+        case SWIZZLE_YYYY:
+           component = 1;
+           break;
+        case SWIZZLE_ZZZZ:
+           component = 2;
+           break;
+        case SWIZZLE_WWWW:
+           component = 3;
+           break;
+        }
+
+        if (component >= 0) {
+           params = c->vp->program.Base.Parameters;
+           f = params->ParameterValues[src->Index][component];
+
+           if (src->Abs)
+              f = fabs(f);
+           if (src->Negate)
+              f = -f;
+           return brw_imm_f(f);
+        }
+      }
+   }
+
    switch (file) {
    case PROGRAM_TEMPORARY:
    case PROGRAM_INPUT:
@@ -1288,7 +1374,7 @@ static void emit_vertex_write( struct brw_vs_compile *c)
       brw_MOV(p, offset(m0, 2), pos);
       brw_MOV(p, offset(m0, 5), pos);
       len_vertex_header = 4;
-   } else if (intel->is_ironlake) {
+   } else if (intel->gen == 5) {
       /* There are 20 DWs (D0-D19) in VUE header on Ironlake:
        * dword 0-3 (m1) of the header is indices, point width, clip flags.
        * dword 4-7 (m2) is the ndc position (set above)
@@ -1657,6 +1743,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
         if_depth++;
         break;
       case OPCODE_ELSE:
+        assert(if_depth > 0);
         if_inst[if_depth-1] = brw_ELSE(p, if_inst[if_depth-1]);
         break;
       case OPCODE_ENDIF:
@@ -1683,7 +1770,7 @@ void brw_vs_emit(struct brw_vs_compile *c )
 
             loop_depth--;
 
-           if (intel->is_ironlake)
+           if (intel->gen == 5)
               br = 2;
 
             inst0 = inst1 = brw_WHILE(p, loop_inst[loop_depth]);