gallium: implement immediates (aka literals) for SSE fragment shaders

This commit is contained in:
Brian Paul 2008-04-11 14:18:07 -06:00
parent 097301395d
commit e3cf0cd6a9
3 changed files with 88 additions and 8 deletions

View file

@ -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:

View file

@ -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
}

View 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;
}