summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Paul <brian.paul@tungstengraphics.com>2008-04-11 14:18:07 -0600
committerBrian Paul <brian.paul@tungstengraphics.com>2008-04-11 14:19:32 -0600
commite3cf0cd6a9f3f072594e5712763b98ce7e579bcf (patch)
treebb18e92a88664a595623ef96a1af7ba93eb005c2
parent097301395d33d57d19bc942f236b4a8c912cc0cc (diff)
gallium: implement immediates (aka literals) for SSE fragment shaders
-rwxr-xr-xsrc/gallium/auxiliary/tgsi/exec/tgsi_sse2.c82
-rwxr-xr-xsrc/gallium/auxiliary/tgsi/exec/tgsi_sse2.h4
-rw-r--r--src/gallium/drivers/softpipe/sp_fs_sse.c10
3 files changed, 88 insertions, 8 deletions
diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
index 93813f36cbe..748c53dbfc9 100755
--- a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
+++ b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.c
@@ -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.
*/
@@ -239,6 +248,16 @@ get_argument(
}
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,
unsigned chan )
@@ -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:
diff --git a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
index 63b8ef39112..fde06047fe8 100755
--- a/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
+++ b/src/gallium/auxiliary/tgsi/exec/tgsi_sse2.h
@@ -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
}
diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c
index 8095d662ee6..9c7948264fe 100644
--- a/src/gallium/drivers/softpipe/sp_fs_sse.c
+++ b/src/gallium/drivers/softpipe/sp_fs_sse.c
@@ -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;
}