gallium: implement immediates (aka literals) for SSE fragment shaders
authorBrian Paul <brian.paul@tungstengraphics.com>
Fri, 11 Apr 2008 20:18:07 +0000 (14:18 -0600)
committerBrian Paul <brian.paul@tungstengraphics.com>
Fri, 11 Apr 2008 20:19:32 +0000 (14:19 -0600)
src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
src/gallium/drivers/softpipe/sp_fs_sse.c

index 93813f36cbe203b5c9b378e09490563d5ad4e8e6..748c53dbfc91f2d4909fecbd27eaa5abde5a8103 100755 (executable)
@@ -225,6 +225,15 @@ get_coef_base( void )
    return get_output_base();
 }
 
+static struct x86_reg
+get_immediate_base( void )
+{
+   return x86_make_reg(
+      file_REG32,
+      reg_DI );
+}
+
+
 /**
  * Data access helpers.
  */
@@ -238,6 +247,16 @@ get_argument(
       (index + 1) * 4 );
 }
 
+static struct x86_reg
+get_immediate(
+   unsigned vec,
+   unsigned chan )
+{
+   return x86_make_disp(
+      get_immediate_base(),
+      (vec * 4 + chan) * 4 );
+}
+
 static struct x86_reg
 get_const(
    unsigned vec,
@@ -572,6 +591,25 @@ emit_const(
       SHUF( 0, 0, 0, 0 ) );
 }
 
+static void
+emit_immediate(
+   struct x86_function *func,
+   unsigned xmm,
+   unsigned vec,
+   unsigned chan )
+{
+   emit_movss(
+      func,
+      make_xmm( xmm ),
+      get_immediate( vec, chan ) );
+   emit_shufps(
+      func,
+      make_xmm( xmm ),
+      make_xmm( xmm ),
+      SHUF( 0, 0, 0, 0 ) );
+}
+
+
 /**
  * Copy a shader input to xmm register
  * \param xmm  the destination xmm register
@@ -1191,6 +1229,14 @@ emit_fetch(
             swizzle );
          break;
 
+      case TGSI_FILE_IMMEDIATE:
+         emit_immediate(
+            func,
+            xmm,
+            reg->SrcRegister.Index,
+            swizzle );
+         break;
+
       case TGSI_FILE_INPUT:
          emit_inputf(
             func,
@@ -2343,15 +2389,21 @@ tgsi_emit_sse2(
  * DECLARATION and INSTRUCTION phase.
  * GP register holding the output argument is aliased with the coeff argument,
  * as outputs are not needed in the DECLARATION phase.
+ *
+ * \param tokens  the TGSI input shader
+ * \param func  the output SSE code/function
+ * \param immediates  buffer to place immediates, later passed to SSE func
  */
 unsigned
 tgsi_emit_sse2_fs(
    struct tgsi_token *tokens,
-   struct x86_function *func )
+   struct x86_function *func,
+   float (*immediates)[4])
 {
    struct tgsi_parse_context parse;
    boolean instruction_phase = FALSE;
    unsigned ok = 1;
+   uint num_immediates = 0;
 
    DUMP_START();
 
@@ -2362,6 +2414,7 @@ tgsi_emit_sse2_fs(
       func,
       get_input_base(),
       get_argument( 0 ) );
+   /* skipping outputs argument here */
    emit_mov(
       func,
       get_const_base(),
@@ -2374,6 +2427,10 @@ tgsi_emit_sse2_fs(
       func,
       get_coef_base(),
       get_argument( 4 ) );
+   emit_mov(
+      func,
+      get_immediate_base(),
+      get_argument( 5 ) );
 
    tgsi_parse_init( &parse, tokens );
 
@@ -2407,9 +2464,26 @@ tgsi_emit_sse2_fs(
          break;
 
       case TGSI_TOKEN_TYPE_IMMEDIATE:
-         /* XXX implement this */
-        ok = 0;
-        debug_printf("failed to emit immediate value to SSE\n");
+         /* simply copy the immediate values into the next immediates[] slot */
+         {
+            const uint size = parse.FullToken.FullImmediate.Immediate.Size - 1;
+            uint i;
+            assert(size <= 4);
+            assert(num_immediates < TGSI_EXEC_NUM_IMMEDIATES);
+            for( i = 0; i < size; i++ ) {
+               immediates[num_immediates][i] =
+                 parse.FullToken.FullImmediate.u.ImmediateFloat32[i].Float;
+            }
+#if 0
+            debug_printf("SSE FS immediate[%d] = %f %f %f %f\n",
+                   num_immediates,
+                   immediates[num_immediates][0],
+                   immediates[num_immediates][1],
+                   immediates[num_immediates][2],
+                   immediates[num_immediates][3]);
+#endif
+            num_immediates++;
+         }
          break;
 
       default:
index 63b8ef3911247f521ed719eed9951ce581641393..fde06047fe8840d40ea6ca4d2c55d098cfa70080 100755 (executable)
@@ -16,7 +16,9 @@ tgsi_emit_sse2(
 unsigned
 tgsi_emit_sse2_fs(
    struct tgsi_token *tokens,
-   struct x86_function *function );
+   struct x86_function *function,
+   float (*immediates)[4]
+ );
 
 #if defined __cplusplus
 }
index 8095d662ee6a88bbaab0045284a5101d89796350..9c7948264fef1a61b7520a9af2d07c1c2bf69ab5 100644 (file)
@@ -51,7 +51,8 @@ typedef void (XSTDCALL *codegen_function)(
    struct tgsi_exec_vector *output,
    float (*constant)[4],
    struct tgsi_exec_vector *temporary,
-   const struct tgsi_interp_coef *coef
+   const struct tgsi_interp_coef *coef,
+   float (*immediates)[4]
    //, const struct tgsi_exec_vector *quadPos
  );
 
@@ -60,6 +61,7 @@ struct sp_sse_fragment_shader {
    struct sp_fragment_shader base;
    struct x86_function             sse2_program;
    codegen_function func;
+   float immediates[TGSI_EXEC_NUM_IMMEDIATES][4];
 };
 
 
@@ -96,7 +98,8 @@ fs_sse_run( struct sp_fragment_shader *base,
                 machine->Outputs,
                 machine->Consts,
                 machine->Temps,
-                machine->InterpCoefs
+                machine->InterpCoefs,
+                 shader->immediates
                 //      , &machine->QuadPos
       );
 
@@ -129,7 +132,8 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
 
    x86_init_func( &shader->sse2_program );
    
-   if (!tgsi_emit_sse2_fs( templ->tokens, &shader->sse2_program )) {
+   if (!tgsi_emit_sse2_fs( templ->tokens, &shader->sse2_program,
+                           shader->immediates)) {
       FREE(shader);
       return NULL;
    }