gallium: add a temporary array register file

like normal temporaries, but allows to define a number of distinct
arrays, all of which make it explicit that they contain /indexable/
registers.
as a side-effect we're adding support for multi-dimensional destination
registers.
The whole thing looks like this:
DCL TEMPX[0][0..128]  # 0 array with 128 registers

ADD TEMPX[0][0], IN[0], IMM[0]
ADD TEMPX[0][1], IN[0], IMM[0]
ABS OUT[0], TEMPX[0][TEMP[0]]
This commit is contained in:
Zack Rusin 2010-06-18 13:41:20 -04:00
parent 2b221e11da
commit 101f792a2a
10 changed files with 330 additions and 136 deletions

View File

@ -632,6 +632,7 @@ tgsi_build_full_instruction(
reg->Register.File,
reg->Register.WriteMask,
reg->Register.Indirect,
reg->Register.Dimension,
reg->Register.Index,
instruction,
header );
@ -659,6 +660,46 @@ tgsi_build_full_instruction(
instruction,
header );
}
if( reg->Register.Dimension ) {
struct tgsi_dimension *dim;
assert( !reg->Dimension.Dimension );
if( maxsize <= size )
return 0;
dim = (struct tgsi_dimension *) &tokens[size];
size++;
*dim = tgsi_build_dimension(
reg->Dimension.Indirect,
reg->Dimension.Index,
instruction,
header );
if( reg->Dimension.Indirect ) {
struct tgsi_src_register *ind;
if( maxsize <= size )
return 0;
ind = (struct tgsi_src_register *) &tokens[size];
size++;
*ind = tgsi_build_src_register(
reg->DimIndirect.File,
reg->DimIndirect.SwizzleX,
reg->DimIndirect.SwizzleY,
reg->DimIndirect.SwizzleZ,
reg->DimIndirect.SwizzleW,
reg->DimIndirect.Negate,
reg->DimIndirect.Absolute,
reg->DimIndirect.Indirect,
reg->DimIndirect.Dimension,
reg->DimIndirect.Index,
instruction,
header );
}
}
}
for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) {
@ -978,6 +1019,7 @@ tgsi_build_dst_register(
unsigned file,
unsigned mask,
unsigned indirect,
unsigned dimension,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
@ -993,6 +1035,7 @@ tgsi_build_dst_register(
dst_register.WriteMask = mask;
dst_register.Index = index;
dst_register.Indirect = indirect;
dst_register.Dimension = dimension;
instruction_grow( instruction, header );
@ -1006,6 +1049,8 @@ tgsi_default_full_dst_register( void )
full_dst_register.Register = tgsi_default_dst_register();
full_dst_register.Indirect = tgsi_default_src_register();
full_dst_register.Dimension = tgsi_default_dimension();
full_dst_register.DimIndirect = tgsi_default_src_register();
return full_dst_register;
}

View File

@ -263,6 +263,7 @@ tgsi_build_dst_register(
unsigned file,
unsigned mask,
unsigned indirect,
unsigned dimension,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header );

View File

@ -102,7 +102,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"IMM",
"PRED",
"SV",
"IMMX"
"IMMX",
"TEMPX"
};
static const char *interpolate_names[] =
@ -191,20 +192,6 @@ static const char *fs_coord_pixel_center_names[] =
};
static void
_dump_register_dst(
struct dump_ctx *ctx,
uint file,
int index)
{
ENM( file, file_names );
CHR( '[' );
SID( index );
CHR( ']' );
}
static void
_dump_register_src(
struct dump_ctx *ctx,
@ -251,30 +238,52 @@ _dump_register_src(
}
}
static void
_dump_register_ind(
struct dump_ctx *ctx,
uint file,
int index,
uint ind_file,
int ind_index,
uint ind_swizzle )
{
ENM( file, file_names );
CHR( '[' );
ENM( ind_file, file_names );
CHR( '[' );
SID( ind_index );
TXT( "]." );
ENM( ind_swizzle, swizzle_names );
if (index != 0) {
if (index > 0)
CHR( '+' );
SID( index );
}
CHR( ']' );
}
static void
_dump_register_dst(
struct dump_ctx *ctx,
const struct tgsi_full_dst_register *dst )
{
ENM(dst->Register.File, file_names);
if (dst->Register.Dimension) {
if (dst->Dimension.Indirect) {
CHR( '[' );
ENM( dst->DimIndirect.File, file_names );
CHR( '[' );
SID( dst->DimIndirect.Index );
TXT( "]." );
ENM( dst->DimIndirect.SwizzleX, swizzle_names );
if (dst->Dimension.Index != 0) {
if (dst->Dimension.Index > 0)
CHR( '+' );
SID( dst->Dimension.Index );
}
CHR( ']' );
} else {
CHR('[');
SID(dst->Dimension.Index);
CHR(']');
}
}
if (dst->Register.Indirect) {
CHR( '[' );
ENM( dst->Indirect.File, file_names );
CHR( '[' );
SID( dst->Indirect.Index );
TXT( "]." );
ENM( dst->Indirect.SwizzleX, swizzle_names );
if (dst->Register.Index != 0) {
if (dst->Register.Index > 0)
CHR( '+' );
SID( dst->Register.Index );
}
CHR( ']' );
} else {
CHR( '[' );
SID( dst->Register.Index );
CHR( ']' );
}
}
static void
_dump_writemask(
struct dump_ctx *ctx,
@ -603,21 +612,7 @@ iter_instruction(
CHR( ',' );
CHR( ' ' );
if (dst->Register.Indirect) {
_dump_register_ind(
ctx,
dst->Register.File,
dst->Register.Index,
dst->Indirect.File,
dst->Indirect.Index,
dst->Indirect.SwizzleX );
}
else {
_dump_register_dst(
ctx,
dst->Register.File,
dst->Register.Index );
}
_dump_register_dst( ctx, dst );
_dump_writemask( ctx, dst->Register.WriteMask );
first_reg = FALSE;

View File

@ -1065,7 +1065,9 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i],
index2D->i[i], index->i[i]);
}*/
chan->u[i] = mach->Inputs[index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i]].xyzw[swizzle].u[i];
chan->u[i] = mach->Inputs[index2D->i[i] *
TGSI_EXEC_MAX_INPUT_ATTRIBS +
index->i[i]].xyzw[swizzle].u[i];
}
break;
@ -1078,6 +1080,16 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach,
}
break;
case TGSI_FILE_TEMPORARY_ARRAY:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
assert(index2D->i[i] < TGSI_EXEC_NUM_TEMP_ARRAYS);
chan->u[i] =
mach->TempArray[index2D->i[i]][index->i[i]].xyzw[swizzle].u[i];
}
break;
case TGSI_FILE_IMMEDIATE:
for (i = 0; i < QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit);
@ -1306,6 +1318,7 @@ store_dest(struct tgsi_exec_machine *mach,
uint i;
union tgsi_exec_channel null;
union tgsi_exec_channel *dst;
union tgsi_exec_channel index2D;
uint execmask = mach->ExecMask;
int offset = 0; /* indirection offset */
int index;
@ -1351,6 +1364,77 @@ store_dest(struct tgsi_exec_machine *mach,
offset = indir_index.i[0];
}
/* There is an extra source register that is a second
* subscript to a register file. Effectively it means that
* the register file is actually a 2D array of registers.
*
* file[3][1],
* where:
* [3] = Dimension.Index
*/
if (reg->Register.Dimension) {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = reg->Dimension.Index;
/* Again, the second subscript index can be addressed indirectly
* identically to the first one.
* Nothing stops us from indirectly addressing the indirect register,
* but there is no need for that, so we won't exercise it.
*
* file[ind[4].y+3][1],
* where:
* ind = DimIndirect.File
* [4] = DimIndirect.Index
* .y = DimIndirect.SwizzleX
*/
if (reg->Dimension.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
unsigned swizzle;
uint i;
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->DimIndirect.Index;
swizzle = tgsi_util_get_src_register_swizzle( &reg->DimIndirect, CHAN_X );
fetch_src_file_channel(mach,
reg->DimIndirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
index2D.i[0] += indir_index.i[0];
index2D.i[1] += indir_index.i[1];
index2D.i[2] += indir_index.i[2];
index2D.i[3] += indir_index.i[3];
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0) {
index2D.i[i] = 0;
}
}
}
/* If by any chance there was a need for a 3D array of register
* files, we would have to check whether Dimension is followed
* by a dimension register and continue the saga.
*/
} else {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = 0;
}
switch (reg->Register.File) {
case TGSI_FILE_NULL:
dst = &null;
@ -1377,6 +1461,16 @@ store_dest(struct tgsi_exec_machine *mach,
dst = &mach->Temps[offset + index].xyzw[chan_index];
break;
case TGSI_FILE_TEMPORARY_ARRAY:
index = reg->Register.Index;
assert( index < TGSI_EXEC_NUM_TEMPS );
assert( index2D.i[0] < TGSI_EXEC_NUM_TEMP_ARRAYS );
/* XXX we use index2D.i[0] here but somehow we might
* end up with someone trying to store indirectly in
* different buffers */
dst = &mach->TempArray[index2D.i[0]][offset + index].xyzw[chan_index];
break;
case TGSI_FILE_ADDRESS:
index = reg->Register.Index;
dst = &mach->Addrs[index].xyzw[chan_index];

View File

@ -93,6 +93,7 @@ struct tgsi_sampler
#define TGSI_EXEC_NUM_TEMPS 128
#define TGSI_EXEC_NUM_IMMEDIATES 256
#define TGSI_EXEC_NUM_TEMP_ARRAYS 8
/*
* Locations of various utility registers (_I = Index, _C = Channel)
@ -237,6 +238,7 @@ struct tgsi_exec_machine
*/
struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS +
TGSI_EXEC_NUM_TEMP_EXTRAS];
struct tgsi_exec_vector TempArray[TGSI_EXEC_NUM_TEMP_ARRAYS][TGSI_EXEC_NUM_TEMPS];
float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];

View File

@ -192,11 +192,6 @@ tgsi_parse_token(
next_token( ctx, &inst->Dst[i].Register );
/*
* No support for indirect or multi-dimensional addressing.
*/
assert( !inst->Dst[i].Register.Dimension );
if( inst->Dst[i].Register.Indirect ) {
next_token( ctx, &inst->Dst[i].Indirect );
@ -206,6 +201,24 @@ tgsi_parse_token(
assert( !inst->Dst[i].Indirect.Dimension );
assert( !inst->Dst[i].Indirect.Indirect );
}
if( inst->Dst[i].Register.Dimension ) {
next_token( ctx, &inst->Dst[i].Dimension );
/*
* No support for multi-dimensional addressing.
*/
assert( !inst->Dst[i].Dimension.Dimension );
if( inst->Dst[i].Dimension.Indirect ) {
next_token( ctx, &inst->Dst[i].DimIndirect );
/*
* No support for indirect or multi-dimensional addressing.
*/
assert( !inst->Dst[i].Indirect.Indirect );
assert( !inst->Dst[i].Indirect.Dimension );
}
}
}
assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );

View File

@ -44,6 +44,8 @@ struct tgsi_full_dst_register
{
struct tgsi_dst_register Register;
struct tgsi_src_register Indirect;
struct tgsi_dimension Dimension;
struct tgsi_src_register DimIndirect;
};
struct tgsi_full_src_register

View File

@ -90,9 +90,18 @@ static void
scan_register_dst(scan_register *reg,
struct tgsi_full_dst_register *dst)
{
fill_scan_register1d(reg,
dst->Register.File,
dst->Register.Index);
if (dst->Register.Dimension) {
/*FIXME: right now we don't support indirect
* multidimensional addressing */
fill_scan_register2d(reg,
dst->Register.File,
dst->Register.Index,
dst->Dimension.Index);
} else {
fill_scan_register1d(reg,
dst->Register.File,
dst->Register.Index);
}
}
static void
@ -236,7 +245,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"IMM",
"PRED",
"SV",
"IMMX"
"IMMX",
"TEMPX"
};
static boolean

View File

@ -281,7 +281,8 @@ static const char *file_names[TGSI_FILE_COUNT] =
"IMM",
"PRED",
"SV",
"IMMX"
"IMMX",
"TEMPX"
};
static boolean
@ -346,12 +347,68 @@ parse_opt_writemask(
return TRUE;
}
static boolean
parse_register_dst( struct translate_ctx *ctx,
uint *file,
int *index );
struct parsed_src_bracket {
/* <register_file_bracket> ::= <file> `['
*/
static boolean
parse_register_file_bracket(
struct translate_ctx *ctx,
uint *file )
{
if (!parse_file( &ctx->cur, file )) {
report_error( ctx, "Unknown register file" );
return FALSE;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != '[') {
report_error( ctx, "Expected `['" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
*/
static boolean
parse_register_file_bracket_index(
struct translate_ctx *ctx,
uint *file,
int *index )
{
uint uindex;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
*index = (int) uindex;
return TRUE;
}
/* Parse simple 1d register operand.
* <register_dst> ::= <register_file_bracket_index> `]'
*/
static boolean
parse_register_1d(struct translate_ctx *ctx,
uint *file,
int *index )
{
if (!parse_register_file_bracket_index( ctx, file, index ))
return FALSE;
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
struct parsed_bracket {
int index;
uint ind_file;
@ -361,21 +418,21 @@ struct parsed_src_bracket {
static boolean
parse_register_src_bracket(
parse_register_bracket(
struct translate_ctx *ctx,
struct parsed_src_bracket *brackets)
struct parsed_bracket *brackets)
{
const char *cur;
uint uindex;
memset(brackets, 0, sizeof(struct parsed_src_bracket));
memset(brackets, 0, sizeof(struct parsed_bracket));
eat_opt_white( &ctx->cur );
cur = ctx->cur;
if (parse_file( &cur, &brackets->ind_file )) {
if (!parse_register_dst( ctx, &brackets->ind_file,
&brackets->ind_index ))
if (!parse_register_1d( ctx, &brackets->ind_file,
&brackets->ind_index ))
return FALSE;
eat_opt_white( &ctx->cur );
@ -444,7 +501,7 @@ parse_register_src_bracket(
static boolean
parse_opt_register_src_bracket(
struct translate_ctx *ctx,
struct parsed_src_bracket *brackets,
struct parsed_bracket *brackets,
int *parsed_brackets)
{
const char *cur = ctx->cur;
@ -456,7 +513,7 @@ parse_opt_register_src_bracket(
++cur;
ctx->cur = cur;
if (!parse_register_src_bracket(ctx, brackets))
if (!parse_register_bracket(ctx, brackets))
return FALSE;
*parsed_brackets = 1;
@ -465,46 +522,6 @@ parse_opt_register_src_bracket(
return TRUE;
}
/* <register_file_bracket> ::= <file> `['
*/
static boolean
parse_register_file_bracket(
struct translate_ctx *ctx,
uint *file )
{
if (!parse_file( &ctx->cur, file )) {
report_error( ctx, "Unknown register file" );
return FALSE;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != '[') {
report_error( ctx, "Expected `['" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
*/
static boolean
parse_register_file_bracket_index(
struct translate_ctx *ctx,
uint *file,
int *index )
{
uint uindex;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
*index = (int) uindex;
return TRUE;
}
/* Parse source register operand.
* <register_src> ::= <register_file_bracket_index> `]' |
@ -516,13 +533,12 @@ static boolean
parse_register_src(
struct translate_ctx *ctx,
uint *file,
struct parsed_src_bracket *brackets)
struct parsed_bracket *brackets)
{
brackets->ind_comp = TGSI_SWIZZLE_X;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_src_bracket( ctx, brackets ))
if (!parse_register_bracket( ctx, brackets ))
return FALSE;
return TRUE;
@ -630,23 +646,19 @@ parse_register_dcl(
}
/* Parse destination register operand.
* <register_dst> ::= <register_file_bracket_index> `]'
*/
/* Parse destination register operand.*/
static boolean
parse_register_dst(
struct translate_ctx *ctx,
uint *file,
int *index )
struct parsed_bracket *brackets)
{
if (!parse_register_file_bracket_index( ctx, file, index ))
brackets->ind_comp = TGSI_SWIZZLE_X;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
ctx->cur++;
if (!parse_register_bracket( ctx, brackets ))
return FALSE;
return TRUE;
}
@ -656,11 +668,14 @@ parse_dst_operand(
struct tgsi_full_dst_register *dst )
{
uint file;
int index;
uint writemask;
const char *cur;
struct parsed_bracket bracket[2];
int parsed_opt_brackets;
if (!parse_register_dst( ctx, &file, &index ))
if (!parse_register_dst( ctx, &file, &bracket[0] ))
return FALSE;
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
return FALSE;
cur = ctx->cur;
@ -670,8 +685,24 @@ parse_dst_operand(
return FALSE;
dst->Register.File = file;
dst->Register.Index = index;
if (parsed_opt_brackets) {
dst->Register.Dimension = 1;
dst->Dimension.Indirect = 0;
dst->Dimension.Dimension = 0;
dst->Dimension.Index = bracket[0].index;
bracket[0] = bracket[1];
}
dst->Register.Index = bracket[0].index;
dst->Register.WriteMask = writemask;
if (bracket[0].ind_file != TGSI_FILE_NULL) {
dst->Register.Indirect = 1;
dst->Indirect.File = bracket[0].ind_file;
dst->Indirect.Index = bracket[0].ind_index;
dst->Indirect.SwizzleX = bracket[0].ind_comp;
dst->Indirect.SwizzleY = bracket[0].ind_comp;
dst->Indirect.SwizzleZ = bracket[0].ind_comp;
dst->Indirect.SwizzleW = bracket[0].ind_comp;
}
return TRUE;
}
@ -720,7 +751,7 @@ parse_src_operand(
uint file;
uint swizzle[4];
boolean parsed_swizzle;
struct parsed_src_bracket bracket[2];
struct parsed_bracket bracket[2];
int parsed_opt_brackets;
if (*ctx->cur == '-') {
@ -836,7 +867,7 @@ parse_instruction(
inst.Predicate.Negate = 1;
}
if (!parse_register_dst( ctx, &file, &index ))
if (!parse_register_1d( ctx, &file, &index ))
return FALSE;
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
@ -1064,7 +1095,7 @@ static boolean parse_declaration( struct translate_ctx *ctx )
decl.Dim.Index2D = brackets[0].first;
}
is_vs_input = (file == TGSI_FILE_INPUT &&
is_vs_input = (file == TGSI_FILE_INPUT &&
ctx->processor == TGSI_PROCESSOR_VERTEX);
is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY);

View File

@ -76,6 +76,7 @@ enum tgsi_file_type {
TGSI_FILE_PREDICATE =8,
TGSI_FILE_SYSTEM_VALUE =9,
TGSI_FILE_IMMEDIATE_ARRAY =10,
TGSI_FILE_TEMPORARY_ARRAY =11,
TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */
};