From 058b978a5ae2a56e09fed6335b686c654444f4ac Mon Sep 17 00:00:00 2001 From: michal Date: Wed, 15 Aug 2007 18:16:11 +0100 Subject: Add UsageMask to DECLARATION in TGSI. Interpolate FS attributes in the shader. Do not copy WPOS in FS. --- src/mesa/pipe/tgsi/core/tgsi_build.c | 4 ++ src/mesa/pipe/tgsi/core/tgsi_build.h | 1 + src/mesa/pipe/tgsi/core/tgsi_dump.c | 31 ++++++++ src/mesa/pipe/tgsi/core/tgsi_exec.c | 127 ++++++++++++++++++++++++++++++++- src/mesa/pipe/tgsi/core/tgsi_exec.h | 52 ++++++++------ src/mesa/pipe/tgsi/core/tgsi_token.h | 37 +++++----- src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c | 76 +++++++++----------- 7 files changed, 244 insertions(+), 84 deletions(-) (limited to 'src/mesa/pipe/tgsi') diff --git a/src/mesa/pipe/tgsi/core/tgsi_build.c b/src/mesa/pipe/tgsi/core/tgsi_build.c index d9c9a45532..d6f8af656a 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_build.c +++ b/src/mesa/pipe/tgsi/core/tgsi_build.c @@ -88,6 +88,7 @@ tgsi_default_declaration( void ) declaration.Size = 1; declaration.File = TGSI_FILE_NULL; declaration.Declare = TGSI_DECLARE_RANGE; + declaration.UsageMask = TGSI_WRITEMASK_XYZW; declaration.Interpolate = 0; declaration.Semantic = 0; declaration.Padding = 0; @@ -100,6 +101,7 @@ struct tgsi_declaration tgsi_build_declaration( unsigned file, unsigned declare, + unsigned usage_mask, unsigned interpolate, unsigned semantic, struct tgsi_header *header ) @@ -112,6 +114,7 @@ tgsi_build_declaration( declaration = tgsi_default_declaration(); declaration.File = file; declaration.Declare = declare; + declaration.UsageMask = usage_mask; declaration.Interpolate = interpolate; declaration.Semantic = semantic; @@ -162,6 +165,7 @@ tgsi_build_full_declaration( *declaration = tgsi_build_declaration( full_decl->Declaration.File, full_decl->Declaration.Declare, + full_decl->Declaration.UsageMask, full_decl->Declaration.Interpolate, full_decl->Declaration.Semantic, header ); diff --git a/src/mesa/pipe/tgsi/core/tgsi_build.h b/src/mesa/pipe/tgsi/core/tgsi_build.h index b3eb0715ee..116c78abf3 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_build.h +++ b/src/mesa/pipe/tgsi/core/tgsi_build.h @@ -38,6 +38,7 @@ struct tgsi_declaration tgsi_build_declaration( unsigned file, unsigned declare, + unsigned usage_mask, unsigned interpolate, unsigned semantic, struct tgsi_header *header ); diff --git a/src/mesa/pipe/tgsi/core/tgsi_dump.c b/src/mesa/pipe/tgsi/core/tgsi_dump.c index 5a9f92004e..622d617e29 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_dump.c +++ b/src/mesa/pipe/tgsi/core/tgsi_dump.c @@ -633,6 +633,22 @@ dump_declaration_short( assert( 0 ); } + if( decl->Declaration.UsageMask != TGSI_WRITEMASK_XYZW ) { + CHR( '.' ); + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_X ) { + CHR( 'x' ); + } + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Y ) { + CHR( 'y' ); + } + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Z ) { + CHR( 'z' ); + } + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_W ) { + CHR( 'w' ); + } + } + if( decl->Declaration.Interpolate ) { TXT( ", " ); ENM( decl->Interpolation.Interpolate, TGSI_INTERPOLATES_SHORT ); @@ -659,6 +675,21 @@ dump_declaration_verbose( ENM( decl->Declaration.File, TGSI_FILES ); TXT( "\nDeclare : " ); ENM( decl->Declaration.Declare, TGSI_DECLARES ); + if( deflt || fd->Declaration.UsageMask != decl->Declaration.UsageMask ) { + TXT( "\nUsageMask : " ); + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_X ) { + CHR( 'X' ); + } + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Y ) { + CHR( 'Y' ); + } + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_Z ) { + CHR( 'Z' ); + } + if( decl->Declaration.UsageMask & TGSI_WRITEMASK_W ) { + CHR( 'W' ); + } + } if( deflt || fd->Declaration.Interpolate != decl->Declaration.Interpolate ) { TXT( "\nInterpolate: " ); UID( decl->Declaration.Interpolate ); diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.c b/src/mesa/pipe/tgsi/core/tgsi_exec.c index 0a34754c40..0ffed20066 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_exec.c +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.c @@ -62,7 +62,7 @@ void tgsi_exec_machine_init( struct tgsi_exec_machine *mach, - struct tgsi_token *tokens, + const struct tgsi_token *tokens, GLuint numSamplers, struct tgsi_sampler *samplers) { @@ -1063,7 +1063,131 @@ fetch_texel( struct tgsi_sampler *sampler, } } +static void +constant_interpolation( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ) +{ + unsigned i; + + for( i = 0; i < QUAD_SIZE; i++ ) { + mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan]; + } +} + +static void +linear_interpolation( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ) +{ + unsigned i; + + for( i = 0; i < QUAD_SIZE; i++ ) { + const float x = mach->Inputs[0].xyzw[0].f[i]; + const float y = mach->Inputs[0].xyzw[1].f[i]; + + mach->Inputs[attrib].xyzw[chan].f[i] = + mach->InterpCoefs[attrib].a0[chan] + + mach->InterpCoefs[attrib].dadx[chan] * x + + mach->InterpCoefs[attrib].dady[chan] * y; + } +} + +static void +perspective_interpolation( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ) +{ + unsigned i; + + for( i = 0; i < QUAD_SIZE; i++ ) { + const float x = mach->Inputs[0].xyzw[0].f[i]; + const float y = mach->Inputs[0].xyzw[1].f[i]; + // WPOS.w here is really 1/w + const float w = 1.0f / mach->Inputs[0].xyzw[3].f[i]; + + mach->Inputs[attrib].xyzw[chan].f[i] = + (mach->InterpCoefs[attrib].a0[chan] + + mach->InterpCoefs[attrib].dadx[chan] * x + + mach->InterpCoefs[attrib].dady[chan] * y) * w; + } +} + +typedef void (* interpolation_func)( + struct tgsi_exec_machine *mach, + unsigned attrib, + unsigned chan ); + +static void +exec_declaration( + struct tgsi_exec_machine *mach, + const struct tgsi_full_declaration *decl ) +{ + if( mach->Processor == TGSI_PROCESSOR_FRAGMENT ) { + if( decl->Declaration.File == TGSI_FILE_INPUT ) { + unsigned first, last, mask, i, j; + interpolation_func interp; + + assert( decl->Declaration.Declare == TGSI_DECLARE_RANGE ); + + first = decl->u.DeclarationRange.First; + last = decl->u.DeclarationRange.Last; + mask = decl->Declaration.UsageMask; + + /* Do not touch WPOS.xy */ + if( first == 0 ) { + mask &= ~TGSI_WRITEMASK_XY; + if( mask == TGSI_WRITEMASK_NONE ) { + first++; + if( first > last ) { + return; + } + } + } + + switch( decl->Interpolation.Interpolate ) { + case TGSI_INTERPOLATE_CONSTANT: + interp = constant_interpolation; + break; + + case TGSI_INTERPOLATE_LINEAR: + interp = linear_interpolation; + break; + case TGSI_INTERPOLATE_PERSPECTIVE: + interp = perspective_interpolation; + break; + + default: + assert( 0 ); + } + + if( mask == TGSI_WRITEMASK_XYZW ) { + unsigned i, j; + + for( i = first; i <= last; i++ ) { + for( j = 0; j < NUM_CHANNELS; j++ ) { + interp( mach, i, j ); + } + } + } + else { + unsigned i, j; + + for( j = 0; j < NUM_CHANNELS; j++ ) { + if( mask & (1 << j) ) { + for( i = first; i <= last; i++ ) { + interp( mach, i, j ); + } + } + } + } + } + } +} static void exec_instruction( @@ -2161,6 +2285,7 @@ tgsi_exec_machine_run2( tgsi_parse_token( &parse ); switch( parse.FullToken.Token.Type ) { case TGSI_TOKEN_TYPE_DECLARATION: + exec_declaration( mach, &parse.FullToken.FullDeclaration ); break; case TGSI_TOKEN_TYPE_IMMEDIATE: break; diff --git a/src/mesa/pipe/tgsi/core/tgsi_exec.h b/src/mesa/pipe/tgsi/core/tgsi_exec.h index eed2207d7d..e5e8c3608e 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_exec.h +++ b/src/mesa/pipe/tgsi/core/tgsi_exec.h @@ -11,23 +11,27 @@ extern "C" { #endif // defined __cplusplus +#define NUM_CHANNELS 4 /* R,G,B,A */ +#define QUAD_SIZE 4 /* 4 pixel/quad */ + union tgsi_exec_channel { - float f[4]; - int i[4]; - unsigned u[4]; + float f[QUAD_SIZE]; + int i[QUAD_SIZE]; + unsigned u[QUAD_SIZE]; }; struct tgsi_exec_vector { - union tgsi_exec_channel xyzw[4]; + union tgsi_exec_channel xyzw[NUM_CHANNELS]; }; - -#define NUM_CHANNELS 4 /* R,G,B,A */ -#ifndef QUAD_SIZE -#define QUAD_SIZE 4 /* 4 pixel/quad */ -#endif +struct tgsi_interp_coef +{ + float a0[NUM_CHANNELS]; /* in an xyzw layout */ + float dadx[NUM_CHANNELS]; + float dady[NUM_CHANNELS]; +}; #define TEX_CACHE_TILE_SIZE 8 #define TEX_CACHE_NUM_ENTRIES 8 @@ -55,8 +59,8 @@ struct tgsi_sampler struct tgsi_exec_labels { - unsigned labels[128][2]; - unsigned count; + unsigned labels[128][2]; + unsigned count; }; #define TGSI_EXEC_TEMP_00000000_I 32 @@ -109,15 +113,15 @@ struct tgsi_exec_cond_state { struct tgsi_exec_cond_regs IfPortion; struct tgsi_exec_cond_regs ElsePortion; - unsigned Condition; - boolean WasElse; + unsigned Condition; + boolean WasElse; }; /* XXX: This is temporary */ struct tgsi_exec_cond_stack { struct tgsi_exec_cond_state States[8]; - unsigned Index; /* into States[] */ + unsigned Index; /* into States[] */ }; struct tgsi_exec_machine @@ -138,15 +142,19 @@ struct tgsi_exec_machine struct tgsi_sampler *Samplers; - float Imms[256][4]; - unsigned ImmLimit; - float (*Consts)[4]; - const struct tgsi_exec_vector *Inputs; + float Imms[256][4]; + unsigned ImmLimit; + float (*Consts)[4]; + struct tgsi_exec_vector *Inputs; struct tgsi_exec_vector *Outputs; - struct tgsi_token *Tokens; - unsigned Processor; + const struct tgsi_token *Tokens; + unsigned Processor; + + /* GEOMETRY processor only. */ + unsigned *Primitives; - unsigned *Primitives; + /* FRAGMENT processor only. */ + const struct tgsi_interp_coef *InterpCoefs; struct tgsi_exec_cond_stack CondStack; #if XXX_SSE @@ -157,7 +165,7 @@ struct tgsi_exec_machine void tgsi_exec_machine_init( struct tgsi_exec_machine *mach, - struct tgsi_token *tokens, + const struct tgsi_token *tokens, unsigned numSamplers, struct tgsi_sampler *samplers); diff --git a/src/mesa/pipe/tgsi/core/tgsi_token.h b/src/mesa/pipe/tgsi/core/tgsi_token.h index f72c7dc4be..3ed341fb7b 100644 --- a/src/mesa/pipe/tgsi/core/tgsi_token.h +++ b/src/mesa/pipe/tgsi/core/tgsi_token.h @@ -52,15 +52,33 @@ struct tgsi_token #define TGSI_DECLARE_RANGE 0 #define TGSI_DECLARE_MASK 1 +#define TGSI_WRITEMASK_NONE 0x00 +#define TGSI_WRITEMASK_X 0x01 +#define TGSI_WRITEMASK_Y 0x02 +#define TGSI_WRITEMASK_XY 0x03 +#define TGSI_WRITEMASK_Z 0x04 +#define TGSI_WRITEMASK_XZ 0x05 +#define TGSI_WRITEMASK_YZ 0x06 +#define TGSI_WRITEMASK_XYZ 0x07 +#define TGSI_WRITEMASK_W 0x08 +#define TGSI_WRITEMASK_XW 0x09 +#define TGSI_WRITEMASK_YW 0x0A +#define TGSI_WRITEMASK_XYW 0x0B +#define TGSI_WRITEMASK_ZW 0x0C +#define TGSI_WRITEMASK_XZW 0x0D +#define TGSI_WRITEMASK_YZW 0x0E +#define TGSI_WRITEMASK_XYZW 0x0F + struct tgsi_declaration { unsigned Type : 4; /* TGSI_TOKEN_TYPE_DECLARATION */ unsigned Size : 8; /* UINT */ unsigned File : 4; /* TGSI_FILE_ */ unsigned Declare : 4; /* TGSI_DECLARE_ */ + unsigned UsageMask : 4; /* TGSI_WRITEMASK_ */ unsigned Interpolate : 1; /* BOOL */ unsigned Semantic : 1; /* BOOL */ - unsigned Padding : 9; + unsigned Padding : 5; unsigned Extended : 1; /* BOOL */ }; @@ -1226,23 +1244,6 @@ struct tgsi_instruction_ext_texture unsigned Extended : 1; /* BOOL */ }; -#define TGSI_WRITEMASK_NONE 0x00 -#define TGSI_WRITEMASK_X 0x01 -#define TGSI_WRITEMASK_Y 0x02 -#define TGSI_WRITEMASK_XY 0x03 -#define TGSI_WRITEMASK_Z 0x04 -#define TGSI_WRITEMASK_XZ 0x05 -#define TGSI_WRITEMASK_YZ 0x06 -#define TGSI_WRITEMASK_XYZ 0x07 -#define TGSI_WRITEMASK_W 0x08 -#define TGSI_WRITEMASK_XW 0x09 -#define TGSI_WRITEMASK_YW 0x0A -#define TGSI_WRITEMASK_XYW 0x0B -#define TGSI_WRITEMASK_ZW 0x0C -#define TGSI_WRITEMASK_XZW 0x0D -#define TGSI_WRITEMASK_YZW 0x0E -#define TGSI_WRITEMASK_XYZW 0x0F - struct tgsi_instruction_ext_predicate { unsigned Type : 4; /* TGSI_INSTRUCTION_EXT_TYPE_PREDICATE */ diff --git a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c index 609d329242..2ac04e8d56 100644 --- a/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c +++ b/src/mesa/pipe/tgsi/mesa/mesa_to_tgsi.c @@ -467,13 +467,15 @@ static struct tgsi_full_declaration make_frag_input_decl( GLuint first, GLuint last, - GLuint interpolate ) + GLuint interpolate, + GLuint usage_mask ) { struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_INPUT; decl.Declaration.Declare = TGSI_DECLARE_RANGE; + decl.Declaration.UsageMask = usage_mask; decl.Declaration.Interpolate = 1; decl.u.DeclarationRange.First = first; decl.u.DeclarationRange.Last = last; @@ -485,13 +487,15 @@ make_frag_input_decl( static struct tgsi_full_declaration make_frag_output_decl( GLuint index, - GLuint semantic_name ) + GLuint semantic_name, + GLuint usage_mask ) { struct tgsi_full_declaration decl; decl = tgsi_default_full_declaration(); decl.Declaration.File = TGSI_FILE_OUTPUT; decl.Declaration.Declare = TGSI_DECLARE_RANGE; + decl.Declaration.UsageMask = usage_mask; decl.Declaration.Semantic = 1; decl.u.DeclarationRange.First = index; decl.u.DeclarationRange.Last = index; @@ -514,6 +518,7 @@ tgsi_mesa_compile_fp_program( struct tgsi_full_dst_register *fulldst; struct tgsi_full_src_register *fullsrc; GLuint inputs_read; + GLboolean reads_wpos; GLuint preamble_size = 0; *(struct tgsi_version *) &tokens[0] = tgsi_build_version(); @@ -523,19 +528,33 @@ tgsi_mesa_compile_fp_program( ti = 2; - /* - * Input 0 is always read, at least implicitly by the MOV instruction generated - * below, so mark it as used. - */ - inputs_read = program->Base.InputsRead | 1; + reads_wpos = program->Base.InputsRead & (1 << FRAG_ATTRIB_WPOS); + inputs_read = program->Base.InputsRead | (1 << FRAG_ATTRIB_WPOS); /* * Declare input attributes. Note that we do not interpolate fragment position. */ + + /* Fragment position. */ + if( reads_wpos ) { + fulldecl = make_frag_input_decl( + 0, + 0, + TGSI_INTERPOLATE_CONSTANT, + TGSI_WRITEMASK_XY ); + ti += tgsi_build_full_declaration( + &fulldecl, + &tokens[ti], + header, + maxTokens - ti ); + } + + /* Fragment zw. */ fulldecl = make_frag_input_decl( 0, 0, - TGSI_INTERPOLATE_CONSTANT ); + TGSI_INTERPOLATE_LINEAR, + reads_wpos ? TGSI_WRITEMASK_ZW : TGSI_WRITEMASK_Z ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], @@ -552,7 +571,8 @@ tgsi_mesa_compile_fp_program( fulldecl = make_frag_input_decl( 1, 1 + count - 1, - TGSI_INTERPOLATE_LINEAR ); + TGSI_INTERPOLATE_LINEAR, + TGSI_WRITEMASK_XYZW ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], @@ -569,7 +589,8 @@ tgsi_mesa_compile_fp_program( fulldecl = make_frag_output_decl( 0, - TGSI_SEMANTIC_DEPTH ); + TGSI_SEMANTIC_DEPTH, + TGSI_WRITEMASK_Z ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], @@ -579,7 +600,8 @@ tgsi_mesa_compile_fp_program( if( program->Base.OutputsWritten & (1 << FRAG_RESULT_COLR) ) { fulldecl = make_frag_output_decl( 1, - TGSI_SEMANTIC_COLOR ); + TGSI_SEMANTIC_COLOR, + TGSI_WRITEMASK_XYZW ); ti += tgsi_build_full_declaration( &fulldecl, &tokens[ti], @@ -587,38 +609,6 @@ tgsi_mesa_compile_fp_program( maxTokens - ti ); } - /* - * Copy input fragment xyz to output xyz. - * If the shader writes depth, do not copy the z component. - */ - - fullinst = tgsi_default_full_instruction(); - - fullinst.Instruction.Opcode = TGSI_OPCODE_MOV; - fullinst.Instruction.NumDstRegs = 1; - fullinst.Instruction.NumSrcRegs = 1; - - fulldst = &fullinst.FullDstRegisters[0]; - fulldst->DstRegister.File = TGSI_FILE_OUTPUT; - fulldst->DstRegister.Index = 0; - if( program->Base.OutputsWritten & (1 << FRAG_RESULT_DEPR) ) { - fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XY; - } - else { - fulldst->DstRegister.WriteMask = TGSI_WRITEMASK_XYZ; - } - - fullsrc = &fullinst.FullSrcRegisters[0]; - fullsrc->SrcRegister.File = TGSI_FILE_INPUT; - fullsrc->SrcRegister.Index = 0; - - ti += tgsi_build_full_instruction( - &fullinst, - &tokens[ti], - header, - maxTokens - ti ); - preamble_size++; - for( i = 0; i < program->Base.NumInstructions; i++ ) { if( compile_instruction( &program->Base.Instructions[i], -- cgit v1.2.3