static boolean
nv30_vertprog_prepare(struct nv30_vpc *vpc)
{
	struct tgsi_parse_context p;
	int nr_imm = 0;

	tgsi_parse_init(&p, vpc->vp->pipe.tokens);
	while (!tgsi_parse_end_of_tokens(&p)) {
		const union tgsi_full_token *tok = &p.FullToken;

		tgsi_parse_token(&p);
		switch(tok->Token.Type) {
		case TGSI_TOKEN_TYPE_IMMEDIATE:
			nr_imm++;
			break;
		default:
			break;
		}
	}
	tgsi_parse_free(&p);

	if (nr_imm) {
		vpc->imm = CALLOC(nr_imm, sizeof(struct nv30_sreg));
		assert(vpc->imm);
	}

	return TRUE;
}
Exemple #2
0
boolean
tgsi_iterate_shader(
   const struct tgsi_token *tokens,
   struct tgsi_iterate_context *ctx )
{
   struct tgsi_parse_context parse;

   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK)
      return FALSE;

   ctx->processor = parse.FullHeader.Processor;

   if (ctx->prolog)
      if (!ctx->prolog( ctx ))
         goto fail;

   while (!tgsi_parse_end_of_tokens( &parse )) {
      tgsi_parse_token( &parse );

      switch (parse.FullToken.Token.Type) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         if (ctx->iterate_instruction)
            if (!ctx->iterate_instruction( ctx, &parse.FullToken.FullInstruction ))
               goto fail;
         break;

      case TGSI_TOKEN_TYPE_DECLARATION:
         if (ctx->iterate_declaration)
            if (!ctx->iterate_declaration( ctx, &parse.FullToken.FullDeclaration ))
               goto fail;
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         if (ctx->iterate_immediate)
            if (!ctx->iterate_immediate( ctx, &parse.FullToken.FullImmediate ))
               goto fail;
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         if (ctx->iterate_property)
            if (!ctx->iterate_property( ctx,  &parse.FullToken.FullProperty ))
               goto fail;
         break;

      default:
         assert( 0 );
      }
   }

   if (ctx->epilog)
      if (!ctx->epilog( ctx ))
         goto fail;

   tgsi_parse_free( &parse );
   return TRUE;

fail:
   tgsi_parse_free( &parse );
   return FALSE;
}
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr,
                     const struct tgsi_token * tokens)
{
    struct tgsi_full_instruction *inst;
    struct tgsi_parse_context parser;
    unsigned imm_index = 0;
    int i;

    /* Allocate constants placeholders.
     *
     * Note: What if declared constants are not contiguous? */
    for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) {
        struct rc_constant constant;
        memset(&constant, 0, sizeof(constant));
        constant.Type = RC_CONSTANT_EXTERNAL;
        constant.Size = 4;
        constant.u.External = i;
        rc_constants_add(&ttr->compiler->Program.Constants, &constant);
    }

    ttr->immediate_offset = ttr->compiler->Program.Constants.Count;

    ttr->imms_to_swizzle = malloc(ttr->info->immediate_count * sizeof(struct swizzled_imms));
    ttr->imms_to_swizzle_count = 0;

    tgsi_parse_init(&parser, tokens);

    while (!tgsi_parse_end_of_tokens(&parser)) {
        tgsi_parse_token(&parser);

        switch (parser.FullToken.Token.Type) {
            case TGSI_TOKEN_TYPE_DECLARATION:
                break;
            case TGSI_TOKEN_TYPE_IMMEDIATE:
                handle_immediate(ttr, &parser.FullToken.FullImmediate, imm_index);
                imm_index++;
                break;
            case TGSI_TOKEN_TYPE_INSTRUCTION:
                inst = &parser.FullToken.FullInstruction;
                /* This hack with the RET opcode woudn't work with
                 * conditionals. */
                if (inst->Instruction.Opcode == TGSI_OPCODE_END ||
                    inst->Instruction.Opcode == TGSI_OPCODE_RET) {
                    break;
                }

                transform_instruction(ttr, inst);
                break;
        }
    }

    tgsi_parse_free(&parser);

    free(ttr->imms_to_swizzle);

    rc_calculate_inputs_outputs(ttr->compiler);
}
static unsigned tgsi_get_processor_type(const struct tgsi_token *tokens)
{
	struct tgsi_parse_context parse;

	if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
		debug_printf("tgsi_parse_init() failed in %s:%i!\n", __func__, __LINE__);
		return ~0;
	}
	return parse.FullHeader.Processor.Processor;
}
Exemple #5
0
int main(int argc, char **argv)
{
    if(argc < 2)
    {
        fprintf(stderr, "Must pass shader source name as argument\n");
        exit(1);
    }
    const char *text = load_text_file(argv[1]);
    if(!text)
    {
        fprintf(stderr, "Unable to open %s\n", argv[1]);
        exit(1);
    }
    struct tgsi_token tokens[1024];
    if(tgsi_text_translate(text, tokens, Elements(tokens)))
    {
        tgsi_dump(tokens, 0); 

        union {
            struct tgsi_header h;
            struct tgsi_token t;
        } hdr;

        hdr.t = tokens[0];
        printf("Header size: %i\n", hdr.h.HeaderSize);
        printf("Body size: %i\n", hdr.h.BodySize);
        int totalSize = hdr.h.HeaderSize + hdr.h.BodySize;

        for(int i=0; i<totalSize; ++i)
        {
            printf("%08x ", *((uint32_t*)&tokens[i]));
        }
        printf("\n");

        /* Parsing test */
        struct tgsi_parse_context ctx = {};
        unsigned status = TGSI_PARSE_OK;
        status = tgsi_parse_init(&ctx, tokens);
        assert(status == TGSI_PARSE_OK);

        while(!tgsi_parse_end_of_tokens(&ctx))
        {
            tgsi_parse_token(&ctx);
            /* declaration / immediate / instruction / property */
            printf("Parsed token! %i\n", ctx.FullToken.Token.Type);
        }

        tgsi_parse_free(&ctx);
    } else {
        fprintf(stderr, "Unable to parse %s\n", argv[1]);
    }

    return 0;
}
Exemple #6
0
unsigned
tgsi_num_tokens(const struct tgsi_token *tokens)
{
   struct tgsi_parse_context ctx;
   if (tgsi_parse_init(&ctx, tokens) == TGSI_PARSE_OK) {
      unsigned len = (ctx.FullHeader.Header.HeaderSize +
                      ctx.FullHeader.Header.BodySize);
      return len;
   }
   return 0;
}
static void scan_immediates(const struct tgsi_token *tokens,
                            const struct tgsi_shader_info *info,
                            struct brw_immediate_data *imm)
{
   struct tgsi_parse_context parse;
   boolean done = FALSE;

   imm->nr = 0;
   imm->data = MALLOC(info->immediate_count * 4 * sizeof(float));

   tgsi_parse_init( &parse, tokens );
   while (!tgsi_parse_end_of_tokens( &parse ) && !done) {
      tgsi_parse_token( &parse );

      switch (parse.FullToken.Token.Type) {
      case TGSI_TOKEN_TYPE_DECLARATION:
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE: {
	 static const float id[4] = {0,0,0,1};
	 const float *value = &parse.FullToken.FullImmediate.u[0].Float;
	 unsigned size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
         unsigned i;

	 for (i = 0; i < size; i++)
	    imm->data[imm->nr][i] = value[i];

	 for (; i < 4; i++)
	    imm->data[imm->nr][i] = id[i];
         
         imm->nr++;
	 break;
      }

      case TGSI_TOKEN_TYPE_INSTRUCTION:
	 done = 1;
	 break;
      }
   }
}
void r300_tgsi_to_rc(struct tgsi_to_rc * ttr, const struct tgsi_token * tokens)
{
    struct tgsi_parse_context parser;
    int i;

    /* Allocate constants placeholders.
     *
     * Note: What if declared constants are not contiguous? */
    for(i = 0; i <= ttr->info->file_max[TGSI_FILE_CONSTANT]; ++i) {
        struct rc_constant constant;
        memset(&constant, 0, sizeof(constant));
        constant.Type = RC_CONSTANT_EXTERNAL;
        constant.Size = 4;
        constant.u.External = i;
        rc_constants_add(&ttr->compiler->Program.Constants, &constant);
    }

    ttr->immediate_offset = ttr->compiler->Program.Constants.Count;

    tgsi_parse_init(&parser, tokens);

    while (!tgsi_parse_end_of_tokens(&parser)) {
        tgsi_parse_token(&parser);

        switch (parser.FullToken.Token.Type) {
        case TGSI_TOKEN_TYPE_DECLARATION:
            break;
        case TGSI_TOKEN_TYPE_IMMEDIATE:
            handle_immediate(ttr, &parser.FullToken.FullImmediate);
            break;
        case TGSI_TOKEN_TYPE_INSTRUCTION:
            transform_instruction(ttr, &parser.FullToken.FullInstruction);
            break;
        }
    }

    tgsi_parse_free(&parser);

    rc_calculate_inputs_outputs(ttr->compiler);
}
Exemple #9
0
/**
 * Check if the given shader is a "passthrough" shader consisting of only
 * MOV instructions of the form:  MOV OUT[n], IN[n]
 *  
 */
boolean
tgsi_is_passthrough_shader(const struct tgsi_token *tokens)
{
   struct tgsi_parse_context parse;

   /**
    ** Setup to begin parsing input shader
    **/
   if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
      debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n");
      return FALSE;
   }

   /**
    ** Loop over incoming program tokens/instructions
    */
   while (!tgsi_parse_end_of_tokens(&parse)) {

      tgsi_parse_token(&parse);

      switch (parse.FullToken.Token.Type) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         {
            struct tgsi_full_instruction *fullinst =
               &parse.FullToken.FullInstruction;
            const struct tgsi_full_src_register *src =
               &fullinst->Src[0];
            const struct tgsi_full_dst_register *dst =
               &fullinst->Dst[0];

            /* Do a whole bunch of checks for a simple move */
            if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
                (src->Register.File != TGSI_FILE_INPUT &&
                 src->Register.File != TGSI_FILE_SYSTEM_VALUE) ||
                dst->Register.File != TGSI_FILE_OUTPUT ||
                src->Register.Index != dst->Register.Index ||

                src->Register.Negate ||
                src->Register.Absolute ||

                src->Register.SwizzleX != TGSI_SWIZZLE_X ||
                src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
                src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
                src->Register.SwizzleW != TGSI_SWIZZLE_W ||

                dst->Register.WriteMask != TGSI_WRITEMASK_XYZW)
            {
               tgsi_parse_free(&parse);
               return FALSE;
            }
         }
         break;

      case TGSI_TOKEN_TYPE_DECLARATION:
         /* fall-through */
      case TGSI_TOKEN_TYPE_IMMEDIATE:
         /* fall-through */
      case TGSI_TOKEN_TYPE_PROPERTY:
         /* fall-through */
      default:
         ; /* no-op */
      }
   }

   tgsi_parse_free(&parse);

   /* if we get here, it's a pass-through shader */
   return TRUE;
}
void
lp_build_tgsi_aos(struct gallivm_state *gallivm,
                  const struct tgsi_token *tokens,
                  struct lp_type type,
                  const unsigned char swizzles[4],
                  LLVMValueRef consts_ptr,
                  const LLVMValueRef *inputs,
                  LLVMValueRef *outputs,
                  struct lp_build_sampler_aos *sampler,
                  const struct tgsi_shader_info *info)
{
   struct lp_build_tgsi_aos_context bld;
   struct tgsi_parse_context parse;
   uint num_immediates = 0;
   unsigned chan;
   int pc = 0;

   /* Setup build context */
   memset(&bld, 0, sizeof bld);
   lp_build_context_init(&bld.bld_base.base, gallivm, type);
   lp_build_context_init(&bld.bld_base.uint_bld, gallivm, lp_uint_type(type));
   lp_build_context_init(&bld.bld_base.int_bld, gallivm, lp_int_type(type));
   lp_build_context_init(&bld.int_bld, gallivm, lp_int_type(type));

   for (chan = 0; chan < 4; ++chan) {
      bld.swizzles[chan] = swizzles[chan];
      bld.inv_swizzles[swizzles[chan]] = chan;
   }

   bld.inputs = inputs;
   bld.outputs = outputs;
   bld.consts_ptr = consts_ptr;
   bld.sampler = sampler;
   bld.indirect_files = info->indirect_files;
   bld.bld_base.emit_swizzle = swizzle_aos;
   bld.bld_base.info = info;

   bld.bld_base.emit_fetch_funcs[TGSI_FILE_CONSTANT] = emit_fetch_constant;
   bld.bld_base.emit_fetch_funcs[TGSI_FILE_IMMEDIATE] = emit_fetch_immediate;
   bld.bld_base.emit_fetch_funcs[TGSI_FILE_INPUT] = emit_fetch_input;
   bld.bld_base.emit_fetch_funcs[TGSI_FILE_TEMPORARY] = emit_fetch_temporary;

   /* Set opcode actions */
   lp_set_default_actions_cpu(&bld.bld_base);

   if (!lp_bld_tgsi_list_init(&bld.bld_base)) {
      return;
   }

   tgsi_parse_init(&parse, tokens);

   while (!tgsi_parse_end_of_tokens(&parse)) {
      tgsi_parse_token(&parse);

      switch(parse.FullToken.Token.Type) {
      case TGSI_TOKEN_TYPE_DECLARATION:
         /* Inputs already interpolated */
         lp_emit_declaration_aos(&bld, &parse.FullToken.FullDeclaration);
         break;

      case TGSI_TOKEN_TYPE_INSTRUCTION:
         /* save expanded instruction */
         lp_bld_tgsi_add_instruction(&bld.bld_base,
                                     &parse.FullToken.FullInstruction);
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         /* simply copy the immediate values into the next immediates[] slot */
         {
            const uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
            float imm[4];
            assert(size <= 4);
            assert(num_immediates < LP_MAX_TGSI_IMMEDIATES);
            for (chan = 0; chan < 4; ++chan) {
               imm[chan] = 0.0f;
            }
            for (chan = 0; chan < size; ++chan) {
               unsigned swizzle = bld.swizzles[chan];
               imm[swizzle] = parse.FullToken.FullImmediate.u[chan].Float;
            }
            bld.immediates[num_immediates] =
                     lp_build_const_aos(gallivm, type,
                                        imm[0], imm[1], imm[2], imm[3],
                                        NULL);
            num_immediates++;
         }
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         break;

      default:
         assert(0);
      }
   }

   while (pc != -1) {
      struct tgsi_full_instruction *instr = bld.bld_base.instructions + pc;
      const struct tgsi_opcode_info *opcode_info =
         tgsi_get_opcode_info(instr->Instruction.Opcode);
      if (!lp_emit_instruction_aos(&bld, instr, opcode_info, &pc))
         _debug_printf("warning: failed to translate tgsi opcode %s to LLVM\n",
                       opcode_info->mnemonic);
   }

   if (0) {
      LLVMBasicBlockRef block = LLVMGetInsertBlock(gallivm->builder);
      LLVMValueRef function = LLVMGetBasicBlockParent(block);
      debug_printf("11111111111111111111111111111 \n");
      tgsi_dump(tokens, 0);
      lp_debug_dump_value(function);
      debug_printf("2222222222222222222222222222 \n");
   }
   tgsi_parse_free(&parse);
   FREE(bld.bld_base.instructions);

   if (0) {
      LLVMModuleRef module = LLVMGetGlobalParent(
         LLVMGetBasicBlockParent(LLVMGetInsertBlock(gallivm->builder)));
      LLVMDumpModule(module);
   }

}
/**
 * Detect any direct relationship between the output color
 */
void
lp_build_tgsi_info(const struct tgsi_token *tokens,
                   struct lp_tgsi_info *info)
{
   struct tgsi_parse_context parse;
   struct analysis_context ctx;
   unsigned index;
   unsigned chan;

   memset(info, 0, sizeof *info);

   tgsi_scan_shader(tokens, &info->base);

   memset(&ctx, 0, sizeof ctx);
   ctx.info = info;

   tgsi_parse_init(&parse, tokens);

   while (!tgsi_parse_end_of_tokens(&parse)) {
      tgsi_parse_token(&parse);

      switch (parse.FullToken.Token.Type) {
      case TGSI_TOKEN_TYPE_DECLARATION:
         break;

      case TGSI_TOKEN_TYPE_INSTRUCTION:
         {
            struct tgsi_full_instruction *inst =
                  &parse.FullToken.FullInstruction;

            if (inst->Instruction.Opcode == TGSI_OPCODE_END ||
                inst->Instruction.Opcode == TGSI_OPCODE_BGNSUB) {
               /* We reached the end of main function body. */
               goto finished;
            }

            analyse_instruction(&ctx, inst);
         }
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         {
            const unsigned size =
                  parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
            assert(size <= 4);
            if (ctx.num_imms < Elements(ctx.imm)) {
               for (chan = 0; chan < size; ++chan) {
                  float value = parse.FullToken.FullImmediate.u[chan].Float;
                  ctx.imm[ctx.num_imms][chan] = value;

                  if (value < 0.0f || value > 1.0f) {
                     info->unclamped_immediates = TRUE;
                  }
               }
               ++ctx.num_imms;
            }
         }
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         break;

      default:
         assert(0);
      }
   }
finished:

   tgsi_parse_free(&parse);


   /*
    * Link the output color values.
    */

   for (index = 0; index < PIPE_MAX_COLOR_BUFS; ++index) {
      const struct lp_tgsi_channel_info null_output[4];
      info->cbuf[index] = null_output;
   }

   for (index = 0; index < info->base.num_outputs; ++index) {
      unsigned semantic_name = info->base.output_semantic_name[index];
      unsigned semantic_index = info->base.output_semantic_index[index];
      if (semantic_name == TGSI_SEMANTIC_COLOR &&
          semantic_index < PIPE_MAX_COLOR_BUFS) {
         info->cbuf[semantic_index] = info->output[index];
      }
   }

   if (gallivm_debug & GALLIVM_DEBUG_TGSI) {
      dump_info(tokens, info);
   }
}
Exemple #12
0
/**
 * Initial pass for fragment program code generation.
 * This function is used by both the GLSL and non-GLSL paths.
 */
int brw_wm_pass_fp( struct brw_wm_compile *c )
{
   struct brw_fragment_shader *fs = c->fp;
   struct tgsi_parse_context parse;
   struct tgsi_full_instruction *inst;
   struct tgsi_full_declaration *decl;
   const float *imm;
   GLuint size;
   GLuint i;

   if (BRW_DEBUG & DEBUG_WM) {
      debug_printf("pre-fp:\n");
      tgsi_dump(fs->tokens, 0); 
   }

   c->fp_pixel_xy = src_undef();
   c->fp_delta_xy = src_undef();
   c->fp_pixel_w = src_undef();
   c->nr_fp_insns = 0;
   c->nr_immediates = 0;


   /* Loop over all instructions doing assorted simplifications and
    * transformations.
    */
   tgsi_parse_init( &parse, fs->tokens );
   while( !tgsi_parse_end_of_tokens( &parse ) ) {
      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_DECLARATION:
	 /* Turn intput declarations into special WM_* instructions.
	  *
	  * XXX: For non-branching shaders, consider deferring variable
	  * initialization as late as possible to minimize register
	  * usage.  This is how the original BRW driver worked.
	  *
	  * In a branching shader, must preamble instructions at decl
	  * time, as instruction order in the shader does not
	  * correspond to the order instructions are executed in the
	  * wild.
	  *
	  * This is where special instructions such as WM_CINTERP,
	  * WM_LINTERP, WM_PINTERP and WM_WPOSXY are emitted to
	  * compute shader inputs from the payload registers and pixel
	  * position.
	  */
         decl = &parse.FullToken.FullDeclaration;
         if( decl->Declaration.File == TGSI_FILE_INPUT ) {
            unsigned first, last, mask;
            unsigned attrib;

            first = decl->Range.First;
            last = decl->Range.Last;
            mask = decl->Declaration.UsageMask;

            for (attrib = first; attrib <= last; attrib++) {
	       emit_interp(c, 
			   attrib, 
			   decl->Semantic.Name,
			   decl->Declaration.Interpolate );
            }
         }
	 
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
	 /* Unlike VS programs we can probably manage fine encoding
	  * immediate values directly into the emitted EU
	  * instructions, as we probably only need to reference one
	  * float value per instruction.  Just save the data for now
	  * and use directly later.
	  */
	 i = c->nr_immediates++;
	 imm = &parse.FullToken.FullImmediate.u[i].Float;
	 size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;

	 if (c->nr_immediates >= BRW_WM_MAX_CONST)
	    return PIPE_ERROR_OUT_OF_MEMORY;

	 for (i = 0; i < size; i++)
	    c->immediate[c->nr_immediates].v[i] = imm[i];

	 for (; i < 4; i++)
	    c->immediate[c->nr_immediates].v[i] = 0.0;

	 c->immediate[c->nr_immediates].nr = size;
	 c->nr_immediates++;
	 break;

      case TGSI_TOKEN_TYPE_INSTRUCTION:
         inst = &parse.FullToken.FullInstruction;
	 emit_insn(c, inst);
	 break;
      }
   }

   if (BRW_DEBUG & DEBUG_WM) {
      brw_wm_print_fp_program( c, "pass_fp" );
      debug_printf("\n");
   }

   return c->error;
}
Exemple #13
0
void
tgsi_dump_c(
   const struct tgsi_token *tokens,
   uint flags )
{
   struct tgsi_parse_context parse;
   struct tgsi_full_instruction fi;
   struct tgsi_full_declaration fd;
   uint ignored = flags & TGSI_DUMP_C_IGNORED;
   uint deflt = flags & TGSI_DUMP_C_DEFAULT;
   uint instno = 0;

   tgsi_parse_init( &parse, tokens );

   TXT( "tgsi-dump begin -----------------" );

   TXT( "\nMajorVersion: " );
   UID( parse.FullVersion.Version.MajorVersion );
   TXT( "\nMinorVersion: " );
   UID( parse.FullVersion.Version.MinorVersion );
   EOL();

   TXT( "\nHeaderSize: " );
   UID( parse.FullHeader.Header.HeaderSize );
   TXT( "\nBodySize  : " );
   UID( parse.FullHeader.Header.BodySize );
   TXT( "\nProcessor : " );
   ENM( parse.FullHeader.Processor.Processor, TGSI_PROCESSOR_TYPES );
   EOL();

   fi = tgsi_default_full_instruction();
   fd = tgsi_default_full_declaration();

   while( !tgsi_parse_end_of_tokens( &parse ) ) {
      tgsi_parse_token( &parse );

      TXT( "\nType       : " );
      ENM( parse.FullToken.Token.Type, TGSI_TOKEN_TYPES );
      if( ignored ) {
         TXT( "\nSize       : " );
         UID( parse.FullToken.Token.Size );
         if( deflt || parse.FullToken.Token.Extended ) {
            TXT( "\nExtended   : " );
            UID( parse.FullToken.Token.Extended );
         }
      }

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_DECLARATION:
         dump_declaration_verbose(
            &parse.FullToken.FullDeclaration,
            ignored,
            deflt,
            &fd );
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         dump_immediate_verbose(
            &parse.FullToken.FullImmediate,
            ignored );
         break;

      case TGSI_TOKEN_TYPE_INSTRUCTION:
         dump_instruction_verbose(
            &parse.FullToken.FullInstruction,
            ignored,
            deflt,
            &fi );
         break;

      default:
         assert( 0 );
      }

      EOL();
   }

   TXT( "\ntgsi-dump end -------------------\n" );

   tgsi_parse_free( &parse );
}
Exemple #14
0
/**
 * Scan the given TGSI shader to collect information such as number of
 * registers used, special instructions used, etc.
 * \return info  the result of the scan
 */
void
tgsi_scan_shader(const struct tgsi_token *tokens,
                 struct tgsi_shader_info *info)
{
   uint procType, i;
   struct tgsi_parse_context parse;
   unsigned current_depth = 0;

   memset(info, 0, sizeof(*info));
   for (i = 0; i < TGSI_FILE_COUNT; i++)
      info->file_max[i] = -1;
   for (i = 0; i < ARRAY_SIZE(info->const_file_max); i++)
      info->const_file_max[i] = -1;
   info->properties[TGSI_PROPERTY_GS_INVOCATIONS] = 1;
   for (i = 0; i < ARRAY_SIZE(info->sampler_targets); i++)
      info->sampler_targets[i] = TGSI_TEXTURE_UNKNOWN;

   /**
    ** Setup to begin parsing input shader
    **/
   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
      debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
      return;
   }
   procType = parse.FullHeader.Processor.Processor;
   assert(procType == PIPE_SHADER_FRAGMENT ||
          procType == PIPE_SHADER_VERTEX ||
          procType == PIPE_SHADER_GEOMETRY ||
          procType == PIPE_SHADER_TESS_CTRL ||
          procType == PIPE_SHADER_TESS_EVAL ||
          procType == PIPE_SHADER_COMPUTE);
   info->processor = procType;

   /**
    ** Loop over incoming program tokens/instructions
    */
   while (!tgsi_parse_end_of_tokens(&parse)) {
      info->num_tokens++;

      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         scan_instruction(info, &parse.FullToken.FullInstruction,
                          &current_depth);
         break;
      case TGSI_TOKEN_TYPE_DECLARATION:
         scan_declaration(info, &parse.FullToken.FullDeclaration);
         break;
      case TGSI_TOKEN_TYPE_IMMEDIATE:
         scan_immediate(info);
         break;
      case TGSI_TOKEN_TYPE_PROPERTY:
         scan_property(info, &parse.FullToken.FullProperty);
         break;
      default:
         assert(!"Unexpected TGSI token type");
      }
   }

   info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] ||
                      info->opcode_count[TGSI_OPCODE_KILL]);

   /* The dimensions of the IN decleration in geometry shader have
    * to be deduced from the type of the input primitive.
    */
   if (procType == PIPE_SHADER_GEOMETRY) {
      unsigned input_primitive =
            info->properties[TGSI_PROPERTY_GS_INPUT_PRIM];
      int num_verts = u_vertices_per_prim(input_primitive);
      int j;
      info->file_count[TGSI_FILE_INPUT] = num_verts;
      info->file_max[TGSI_FILE_INPUT] =
            MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
      for (j = 0; j < num_verts; ++j) {
         info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
      }
   }

   tgsi_parse_free(&parse);
}
Exemple #15
0
/* Calculate interpolants for triangle and line rasterization.
 */
static void upload_sf_prog( struct brw_context *brw )
{
   const struct brw_fragment_program *fs = brw->attribs.FragmentProgram;
   struct brw_sf_prog_key key;
   struct tgsi_parse_context parse;
   int i, done = 0;


   memset(&key, 0, sizeof(key));

   /* Populate the key, noting state dependencies:
    */
   /* CACHE_NEW_VS_PROG */
   key.vp_output_count = brw->vs.prog_data->outputs_written;

   /* BRW_NEW_FS */
   key.fp_input_count = brw->attribs.FragmentProgram->info.file_max[TGSI_FILE_INPUT] + 1;


   /* BRW_NEW_REDUCED_PRIMITIVE */
   switch (brw->reduced_primitive) {
   case PIPE_PRIM_TRIANGLES:
//      if (key.attrs & (1<<VERT_RESULT_EDGE))
//	 key.primitive = SF_UNFILLED_TRIS;
//      else
      key.primitive = SF_TRIANGLES;
      break;
   case PIPE_PRIM_LINES:
      key.primitive = SF_LINES;
      break;
   case PIPE_PRIM_POINTS:
      key.primitive = SF_POINTS;
      break;
   }



   /* Scan fp inputs to figure out what interpolation modes are
    * required for each incoming vp output.  There is an assumption
    * that the state tracker makes sure there is a 1:1 linkage between
    * these sets of attributes (XXX: position??)
    */
   tgsi_parse_init( &parse, fs->program.tokens );
   while( !done &&
	  !tgsi_parse_end_of_tokens( &parse ) ) 
   {
      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_DECLARATION:
	 if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT) 
	 {
	    int first = parse.FullToken.FullDeclaration.DeclarationRange.First;
	    int last = parse.FullToken.FullDeclaration.DeclarationRange.Last;
	    int interp_mode = parse.FullToken.FullDeclaration.Declaration.Interpolate;
	    //int semantic = parse.FullToken.FullDeclaration.Semantic.SemanticName;
	    //int semantic_index = parse.FullToken.FullDeclaration.Semantic.SemanticIndex;

	    debug_printf("fs input %d..%d interp mode %d\n", first, last, interp_mode);
	    
	    switch (interp_mode) {
	    case TGSI_INTERPOLATE_CONSTANT:
	       for (i = first; i <= last; i++) 
		  key.const_mask |= (1 << i);
	       break;
	    case TGSI_INTERPOLATE_LINEAR:
	       for (i = first; i <= last; i++) 
		  key.linear_mask |= (1 << i);
	       break;
	    case TGSI_INTERPOLATE_PERSPECTIVE:
	       for (i = first; i <= last; i++) 
		  key.persp_mask |= (1 << i);
	       break;
	    default:
	       break;
	    }

	    /* Also need stuff for flat shading, twosided color.
	     */

	 }
	 break;
      default:
	 done = 1;
	 break;
      }
   }

   /* Hack: Adjust for position.  Optimize away when not required (ie
    * for perspective interpolation).
    */
   key.persp_mask <<= 1;
   key.linear_mask <<= 1; 
   key.linear_mask |= 1;
   key.const_mask <<= 1;

   debug_printf("key.persp_mask: %x\n", key.persp_mask);
   debug_printf("key.linear_mask: %x\n", key.linear_mask);
   debug_printf("key.const_mask: %x\n", key.const_mask);


//   key.do_point_sprite = brw->attribs.Point->PointSprite;
//   key.SpriteOrigin = brw->attribs.Point->SpriteOrigin;

//   key.do_flat_shading = (brw->attribs.Raster->flatshade);
//   key.do_twoside_color = (brw->attribs.Light->Enabled && brw->attribs.Light->Model.TwoSide);

//   if (key.do_twoside_color)
//      key.frontface_ccw = (brw->attribs.Polygon->FrontFace == GL_CCW);


   if (!search_cache(brw, &key))
      compile_sf_prog( brw, &key );
}
static void
nv30_vertprog_translate(struct nv30_context *nv30,
			struct nv30_vertex_program *vp)
{
	struct tgsi_parse_context parse;
	struct nv30_vpc *vpc = NULL;

	tgsi_dump(vp->pipe.tokens,0);

	vpc = CALLOC(1, sizeof(struct nv30_vpc));
	if (!vpc)
		return;
	vpc->vp = vp;
	vpc->high_temp = -1;

	if (!nv30_vertprog_prepare(vpc)) {
		FREE(vpc);
		return;
	}

	tgsi_parse_init(&parse, vp->pipe.tokens);

	while (!tgsi_parse_end_of_tokens(&parse)) {
		tgsi_parse_token(&parse);

		switch (parse.FullToken.Token.Type) {
		case TGSI_TOKEN_TYPE_DECLARATION:
		{
			const struct tgsi_full_declaration *fdec;
			fdec = &parse.FullToken.FullDeclaration;
			switch (fdec->Declaration.File) {
			case TGSI_FILE_OUTPUT:
				if (!nv30_vertprog_parse_decl_output(vpc, fdec))
					goto out_err;
				break;
			default:
				break;
			}
		}
			break;
		case TGSI_TOKEN_TYPE_IMMEDIATE:
		{
			const struct tgsi_full_immediate *imm;

			imm = &parse.FullToken.FullImmediate;
			assert(imm->Immediate.DataType == TGSI_IMM_FLOAT32);
			assert(imm->Immediate.NrTokens == 4 + 1);
			vpc->imm[vpc->nr_imm++] =
				constant(vpc, -1,
					 imm->u[0].Float,
					 imm->u[1].Float,
					 imm->u[2].Float,
					 imm->u[3].Float);
		}
			break;
		case TGSI_TOKEN_TYPE_INSTRUCTION:
		{
			const struct tgsi_full_instruction *finst;
			finst = &parse.FullToken.FullInstruction;
			if (!nv30_vertprog_parse_instruction(vpc, finst))
				goto out_err;
		}
			break;
		default:
			break;
		}
	}

	vp->insns[vp->nr_insns - 1].data[3] |= NV30_VP_INST_LAST;
	vp->translated = TRUE;
out_err:
	tgsi_parse_free(&parse);
	FREE(vpc);
}
Exemple #17
0
/**
 * Apply user-defined transformations to the input shader to produce
 * the output shader.
 * For example, a register search-and-replace operation could be applied
 * by defining a transform_instruction() callback that examined and changed
 * the instruction src/dest regs.
 *
 * \return number of tokens emitted
 */
int
tgsi_transform_shader(const struct tgsi_token *tokens_in,
                      struct tgsi_token *tokens_out,
                      uint max_tokens_out,
                      struct tgsi_transform_context *ctx)
{
   uint procType;

   /* input shader */
   struct tgsi_parse_context parse;

   /* output shader */
   struct tgsi_processor *processor;


   /**
    ** callback context init
    **/
   ctx->emit_instruction = emit_instruction;
   ctx->emit_declaration = emit_declaration;
   ctx->emit_immediate = emit_immediate;
   ctx->tokens_out = tokens_out;
   ctx->max_tokens_out = max_tokens_out;


   /**
    ** Setup to begin parsing input shader
    **/
   if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
      debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
      return -1;
   }
   procType = parse.FullHeader.Processor.Processor;
   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
          procType == TGSI_PROCESSOR_VERTEX ||
          procType == TGSI_PROCESSOR_GEOMETRY);


   /**
    **  Setup output shader
    **/
   *(struct tgsi_version *) &tokens_out[0] = tgsi_build_version();

   ctx->header = (struct tgsi_header *) (tokens_out + 1);
   *ctx->header = tgsi_build_header();

   processor = (struct tgsi_processor *) (tokens_out + 2);
   *processor = tgsi_build_processor( procType, ctx->header );

   ctx->ti = 3;


   /**
    ** Loop over incoming program tokens/instructions
    */
   while( !tgsi_parse_end_of_tokens( &parse ) ) {

      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         {
            struct tgsi_full_instruction *fullinst
               = &parse.FullToken.FullInstruction;

            if (ctx->transform_instruction)
               ctx->transform_instruction(ctx, fullinst);
            else
               ctx->emit_instruction(ctx, fullinst);
         }
         break;

      case TGSI_TOKEN_TYPE_DECLARATION:
         {
            struct tgsi_full_declaration *fulldecl
               = &parse.FullToken.FullDeclaration;

            if (ctx->transform_declaration)
               ctx->transform_declaration(ctx, fulldecl);
            else
               ctx->emit_declaration(ctx, fulldecl);
         }
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         {
            struct tgsi_full_immediate *fullimm
               = &parse.FullToken.FullImmediate;

            if (ctx->transform_immediate)
               ctx->transform_immediate(ctx, fullimm);
            else
               ctx->emit_immediate(ctx, fullimm);
         }
         break;

      default:
         assert( 0 );
      }
   }

   if (ctx->epilog) {
      ctx->epilog(ctx);
   }

   tgsi_parse_free (&parse);

   return ctx->ti;
}
/**
 * Scan the given TGSI shader to collect information such as number of
 * registers used, special instructions used, etc.
 * \return info  the result of the scan
 */
void
tgsi_scan_shader(const struct tgsi_token *tokens,
                 struct tgsi_shader_info *info)
{
   uint procType, i;
   struct tgsi_parse_context parse;

   memset(info, 0, sizeof(*info));
   for (i = 0; i < TGSI_FILE_COUNT; i++)
      info->file_max[i] = -1;
   for (i = 0; i < Elements(info->const_file_max); i++)
      info->const_file_max[i] = -1;

   /**
    ** Setup to begin parsing input shader
    **/
   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
      debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
      return;
   }
   procType = parse.FullHeader.Processor.Processor;
   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
          procType == TGSI_PROCESSOR_VERTEX ||
          procType == TGSI_PROCESSOR_GEOMETRY ||
          procType == TGSI_PROCESSOR_COMPUTE);
   info->processor = procType;


   /**
    ** Loop over incoming program tokens/instructions
    */
   while( !tgsi_parse_end_of_tokens( &parse ) ) {

      info->num_tokens++;

      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         {
            const struct tgsi_full_instruction *fullinst
               = &parse.FullToken.FullInstruction;
            uint i;

            assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
            info->opcode_count[fullinst->Instruction.Opcode]++;

            for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
               const struct tgsi_full_src_register *src =
                  &fullinst->Src[i];
               int ind = src->Register.Index;

               /* Mark which inputs are effectively used */
               if (src->Register.File == TGSI_FILE_INPUT) {
                  unsigned usage_mask;
                  usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
                  if (src->Register.Indirect) {
                     for (ind = 0; ind < info->num_inputs; ++ind) {
                        info->input_usage_mask[ind] |= usage_mask;
                     }
                  } else {
                     assert(ind >= 0);
                     assert(ind < PIPE_MAX_SHADER_INPUTS);
                     info->input_usage_mask[ind] |= usage_mask;
                  }

                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
                      info->reads_position &&
                      src->Register.Index == 0 &&
                      (src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
                       src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
                       src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
                       src->Register.SwizzleW == TGSI_SWIZZLE_Z)) {
                     info->reads_z = TRUE;
                  }
               }

               /* check for indirect register reads */
               if (src->Register.Indirect) {
                  info->indirect_files |= (1 << src->Register.File);
               }

               /* MSAA samplers */
               if (src->Register.File == TGSI_FILE_SAMPLER) {
                  assert(fullinst->Instruction.Texture);
                  assert(src->Register.Index < Elements(info->is_msaa_sampler));

                  if (fullinst->Instruction.Texture &&
                      (fullinst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ||
                       fullinst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA)) {
                     info->is_msaa_sampler[src->Register.Index] = TRUE;
                  }
               }
            }

            /* check for indirect register writes */
            for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
               const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
               if (dst->Register.Indirect) {
                  info->indirect_files |= (1 << dst->Register.File);
               }
            }

            info->num_instructions++;
         }
         break;

      case TGSI_TOKEN_TYPE_DECLARATION:
         {
            const struct tgsi_full_declaration *fulldecl
               = &parse.FullToken.FullDeclaration;
            const uint file = fulldecl->Declaration.File;
            uint reg;
            for (reg = fulldecl->Range.First;
                 reg <= fulldecl->Range.Last;
                 reg++) {
               unsigned semName = fulldecl->Semantic.Name;
               unsigned semIndex = fulldecl->Semantic.Index;

               /* only first 32 regs will appear in this bitfield */
               info->file_mask[file] |= (1 << reg);
               info->file_count[file]++;
               info->file_max[file] = MAX2(info->file_max[file], (int)reg);

               if (file == TGSI_FILE_CONSTANT) {
                  int buffer = 0;

                  if (fulldecl->Declaration.Dimension)
                     buffer = fulldecl->Dim.Index2D;

                  info->const_file_max[buffer] =
                        MAX2(info->const_file_max[buffer], (int)reg);
               }
               else if (file == TGSI_FILE_INPUT) {
                  info->input_semantic_name[reg] = (ubyte) semName;
                  info->input_semantic_index[reg] = (ubyte) semIndex;
                  info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
                  info->input_interpolate_loc[reg] = (ubyte)fulldecl->Interp.Location;
                  info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
                  info->num_inputs++;

                  if (semName == TGSI_SEMANTIC_PRIMID)
                     info->uses_primid = TRUE;
                  else if (procType == TGSI_PROCESSOR_FRAGMENT) {
                     if (semName == TGSI_SEMANTIC_POSITION)
                        info->reads_position = TRUE;
                     else if (semName == TGSI_SEMANTIC_FACE)
                        info->uses_frontface = TRUE;
                  }
               }
               else if (file == TGSI_FILE_SYSTEM_VALUE) {
                  unsigned index = fulldecl->Range.First;

                  info->system_value_semantic_name[index] = semName;
                  info->num_system_values = MAX2(info->num_system_values,
                                                 index + 1);

                  if (semName == TGSI_SEMANTIC_INSTANCEID) {
                     info->uses_instanceid = TRUE;
                  }
                  else if (semName == TGSI_SEMANTIC_VERTEXID) {
                     info->uses_vertexid = TRUE;
                  }
                  else if (semName == TGSI_SEMANTIC_PRIMID) {
                     info->uses_primid = TRUE;
                  }
               }
               else if (file == TGSI_FILE_OUTPUT) {
                  info->output_semantic_name[reg] = (ubyte) semName;
                  info->output_semantic_index[reg] = (ubyte) semIndex;
                  info->num_outputs++;

                  if (procType == TGSI_PROCESSOR_VERTEX ||
                      procType == TGSI_PROCESSOR_GEOMETRY) {
                     if (semName == TGSI_SEMANTIC_CLIPDIST) {
                        info->num_written_clipdistance +=
                           util_bitcount(fulldecl->Declaration.UsageMask);
                     }
                     else if (semName == TGSI_SEMANTIC_CULLDIST) {
                        info->num_written_culldistance +=
                           util_bitcount(fulldecl->Declaration.UsageMask);
                     }
                  }

                  if (procType == TGSI_PROCESSOR_FRAGMENT) {
                     if (semName == TGSI_SEMANTIC_POSITION) {
                        info->writes_z = TRUE;
                     }
                     else if (semName == TGSI_SEMANTIC_STENCIL) {
                        info->writes_stencil = TRUE;
                     }
                  }

                  if (procType == TGSI_PROCESSOR_VERTEX) {
                     if (semName == TGSI_SEMANTIC_EDGEFLAG) {
                        info->writes_edgeflag = TRUE;
                     }
                  }

                  if (procType == TGSI_PROCESSOR_GEOMETRY) {
                     if (semName == TGSI_SEMANTIC_VIEWPORT_INDEX) {
                        info->writes_viewport_index = TRUE;
                     }
                     else if (semName == TGSI_SEMANTIC_LAYER) {
                        info->writes_layer = TRUE;
                     }
                  }
               }
            }
         }
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         {
            uint reg = info->immediate_count++;
            uint file = TGSI_FILE_IMMEDIATE;

            info->file_mask[file] |= (1 << reg);
            info->file_count[file]++;
            info->file_max[file] = MAX2(info->file_max[file], (int)reg);
         }
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         {
            const struct tgsi_full_property *fullprop
               = &parse.FullToken.FullProperty;
            unsigned name = fullprop->Property.PropertyName;

            assert(name < Elements(info->properties));
            info->properties[name] = fullprop->u[0].Data;
         }
         break;

      default:
         assert( 0 );
      }
   }

   info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] ||
                      info->opcode_count[TGSI_OPCODE_KILL]);

   /* The dimensions of the IN decleration in geometry shader have
    * to be deduced from the type of the input primitive.
    */
   if (procType == TGSI_PROCESSOR_GEOMETRY) {
      unsigned input_primitive =
            info->properties[TGSI_PROPERTY_GS_INPUT_PRIM];
      int num_verts = u_vertices_per_prim(input_primitive);
      int j;
      info->file_count[TGSI_FILE_INPUT] = num_verts;
      info->file_max[TGSI_FILE_INPUT] =
            MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
      for (j = 0; j < num_verts; ++j) {
         info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
      }
   }

   tgsi_parse_free (&parse);
}
Exemple #19
0
int main(int argc, char **argv)
{
	int ret = 0, n = 1;
	const char *filename;
	struct tgsi_token toks[65536];
	struct tgsi_parse_context parse;
	struct ir3_compiler *compiler;
	struct ir3_shader_variant v;
	struct ir3_shader_key key = {};
	const char *info;
	void *ptr;
	size_t size;

	fd_mesa_debug |= FD_DBG_DISASM;

	/* cmdline args which impact shader variant get spit out in a
	 * comment on the first line..  a quick/dirty way to preserve
	 * that info so when ir3test recompiles the shader with a new
	 * compiler version, we use the same shader-key settings:
	 */
	debug_printf("; options:");

	while (n < argc) {
		if (!strcmp(argv[n], "--verbose")) {
			fd_mesa_debug |= FD_DBG_MSGS | FD_DBG_OPTMSGS;
			n++;
			continue;
		}

		if (!strcmp(argv[n], "--binning-pass")) {
			debug_printf(" %s", argv[n]);
			key.binning_pass = true;
			n++;
			continue;
		}

		if (!strcmp(argv[n], "--color-two-side")) {
			debug_printf(" %s", argv[n]);
			key.color_two_side = true;
			n++;
			continue;
		}

		if (!strcmp(argv[n], "--half-precision")) {
			debug_printf(" %s", argv[n]);
			key.half_precision = true;
			n++;
			continue;
		}

		if (!strcmp(argv[n], "--saturate-s")) {
			debug_printf(" %s %s", argv[n], argv[n+1]);
			key.vsaturate_s = key.fsaturate_s = strtol(argv[n+1], NULL, 0);
			n += 2;
			continue;
		}

		if (!strcmp(argv[n], "--saturate-t")) {
			debug_printf(" %s %s", argv[n], argv[n+1]);
			key.vsaturate_t = key.fsaturate_t = strtol(argv[n+1], NULL, 0);
			n += 2;
			continue;
		}

		if (!strcmp(argv[n], "--saturate-r")) {
			debug_printf(" %s %s", argv[n], argv[n+1]);
			key.vsaturate_r = key.fsaturate_r = strtol(argv[n+1], NULL, 0);
			n += 2;
			continue;
		}

		if (!strcmp(argv[n], "--help")) {
			print_usage();
			return 0;
		}

		break;
	}
	debug_printf("\n");

	filename = argv[n];

	memset(&v, 0, sizeof(v));
	v.key = key;

	ret = read_file(filename, &ptr, &size);
	if (ret) {
		print_usage();
		return ret;
	}

	if (fd_mesa_debug & FD_DBG_OPTMSGS)
		debug_printf("%s\n", (char *)ptr);

	if (!tgsi_text_translate(ptr, toks, Elements(toks)))
		errx(1, "could not parse `%s'", filename);

	tgsi_parse_init(&parse, toks);
	switch (parse.FullHeader.Processor.Processor) {
	case TGSI_PROCESSOR_FRAGMENT:
		v.type = SHADER_FRAGMENT;
		break;
	case TGSI_PROCESSOR_VERTEX:
		v.type = SHADER_VERTEX;
		break;
	case TGSI_PROCESSOR_COMPUTE:
		v.type = SHADER_COMPUTE;
		break;
	}

	/* TODO cmdline option to target different gpus: */
	compiler = ir3_compiler_create(320);

	info = "NIR compiler";
	ret = ir3_compile_shader_nir(compiler, &v, toks, key);
	if (ret) {
		fprintf(stderr, "compiler failed!\n");
		return ret;
	}
	dump_info(&v, info);
}
Exemple #20
0
/* Build a struct like the one we'd like the state tracker to pass to
 * us.
 */
static void update_sf_linkage( struct brw_context *brw )
{
   const struct brw_vertex_program *vs = brw->attribs.VertexProgram;
   const struct brw_fragment_program *fs = brw->attribs.FragmentProgram;
   struct pipe_setup_linkage state;
   struct tgsi_parse_context parse;

   int i, j;
   int nr_vp_outputs = 0;
   int done = 0;

   struct { 
      unsigned semantic:8;
      unsigned semantic_index:16;
   } fp_semantic[32], vp_semantic[32];

   memset(&state, 0, sizeof(state));

   state.fp_input_count = 0;



   


   assert(state.fp_input_count == fs->program.num_inputs);

      
   /* Then scan vp outputs
    */
   done = 0;
   tgsi_parse_init( &parse, vs->program.tokens );
   while( !done &&
	  !tgsi_parse_end_of_tokens( &parse ) ) 
   {
      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_DECLARATION:
	 if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_INPUT) 
	 {
	    int first = parse.FullToken.FullDeclaration.DeclarationRange.First;
	    int last = parse.FullToken.FullDeclaration.DeclarationRange.Last;

	    for (i = first; i < last; i++) {
	       vp_semantic[i].semantic = 
		  parse.FullToken.FullDeclaration.Semantic.SemanticName;
	       vp_semantic[i].semantic_index = 
		  parse.FullToken.FullDeclaration.Semantic.SemanticIndex;
	    }
	    
	    assert(last > nr_vp_outputs);
	    nr_vp_outputs = last;
	 }
	 break;
      default:
	 done = 1;
	 break;
      }
   }


   /* Now match based on semantic information.
    */
   for (i = 0; i< state.fp_input_count; i++) {
      for (j = 0; j < nr_vp_outputs; j++) {
	 if (fp_semantic[i].semantic == vp_semantic[j].semantic &&
	     fp_semantic[i].semantic_index == vp_semantic[j].semantic_index) {
	    state.fp_input[i].vp_output = j;
	 }
      }
      if (fp_semantic[i].semantic == TGSI_SEMANTIC_COLOR) {
	 for (j = 0; j < nr_vp_outputs; j++) {
	    if (TGSI_SEMANTIC_BCOLOR == vp_semantic[j].semantic &&
		fp_semantic[i].semantic_index == vp_semantic[j].semantic_index) {
	       state.fp_input[i].bf_vp_output = j;
	    }
	 }
      }
   }

   if (memcmp(&brw->sf.linkage, &state, sizeof(state)) != 0) {
      brw->sf.linkage = state;
      brw->state.dirty.brw |= BRW_NEW_SF_LINKAGE;
   }
}
Exemple #21
0
/**
 * Scan the given TGSI shader to collect information such as number of
 * registers used, special instructions used, etc.
 * \return info  the result of the scan
 */
void
tgsi_scan_shader(const struct tgsi_token *tokens,
                 struct tgsi_shader_info *info)
{
   uint procType, i;
   struct tgsi_parse_context parse;

   memset(info, 0, sizeof(*info));
   for (i = 0; i < TGSI_FILE_COUNT; i++)
      info->file_max[i] = -1;

   /**
    ** Setup to begin parsing input shader
    **/
   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
      debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
      return;
   }
   procType = parse.FullHeader.Processor.Processor;
   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
          procType == TGSI_PROCESSOR_VERTEX ||
          procType == TGSI_PROCESSOR_GEOMETRY ||
          procType == TGSI_PROCESSOR_COMPUTE);
   info->processor = procType;


   /**
    ** Loop over incoming program tokens/instructions
    */
   while( !tgsi_parse_end_of_tokens( &parse ) ) {

      info->num_tokens++;

      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         {
            const struct tgsi_full_instruction *fullinst
               = &parse.FullToken.FullInstruction;
            uint i;

            assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
            info->opcode_count[fullinst->Instruction.Opcode]++;

            for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
               const struct tgsi_full_src_register *src =
                  &fullinst->Src[i];
               int ind = src->Register.Index;

               /* Mark which inputs are effectively used */
               if (src->Register.File == TGSI_FILE_INPUT) {
                  unsigned usage_mask;
                  usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
                  if (src->Register.Indirect) {
                     for (ind = 0; ind < info->num_inputs; ++ind) {
                        info->input_usage_mask[ind] |= usage_mask;
                     }
                  } else {
                     assert(ind >= 0);
                     assert(ind < PIPE_MAX_SHADER_INPUTS);
                     info->input_usage_mask[ind] |= usage_mask;
                  }

                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
                      src->Register.File == TGSI_FILE_INPUT &&
                      info->reads_position &&
                      src->Register.Index == 0 &&
                      (src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
                       src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
                       src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
                       src->Register.SwizzleW == TGSI_SWIZZLE_Z)) {
                     info->reads_z = TRUE;
                  }
               }

               /* check for indirect register reads */
               if (src->Register.Indirect) {
                  info->indirect_files |= (1 << src->Register.File);
               }
            }

            /* check for indirect register writes */
            for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
               const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
               if (dst->Register.Indirect) {
                  info->indirect_files |= (1 << dst->Register.File);
               }
            }

            info->num_instructions++;
         }
         break;

      case TGSI_TOKEN_TYPE_DECLARATION:
         {
            const struct tgsi_full_declaration *fulldecl
               = &parse.FullToken.FullDeclaration;
            const uint file = fulldecl->Declaration.File;
            uint reg;
            for (reg = fulldecl->Range.First;
                 reg <= fulldecl->Range.Last;
                 reg++) {

               /* only first 32 regs will appear in this bitfield */
               info->file_mask[file] |= (1 << reg);
               info->file_count[file]++;
               info->file_max[file] = MAX2(info->file_max[file], (int)reg);

               if (file == TGSI_FILE_INPUT) {
                  info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
                  info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
                  info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
                  info->input_centroid[reg] = (ubyte)fulldecl->Interp.Centroid;
                  info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
                  info->num_inputs++;

                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
                        info->reads_position = TRUE;
               }
               else if (file == TGSI_FILE_SYSTEM_VALUE) {
                  unsigned index = fulldecl->Range.First;
                  unsigned semName = fulldecl->Semantic.Name;

                  info->system_value_semantic_name[index] = semName;
                  info->num_system_values = MAX2(info->num_system_values,
                                                 index + 1);

                  /*
                  info->system_value_semantic_name[info->num_system_values++] = 
                     fulldecl->Semantic.Name;
                  */

                  if (fulldecl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) {
                     info->uses_instanceid = TRUE;
                  }
                  else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) {
                     info->uses_vertexid = TRUE;
                  } else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_PRIMID) {
                     info->uses_primid = TRUE;
                  }
               }
               else if (file == TGSI_FILE_OUTPUT) {
                  info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
                  info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
                  info->num_outputs++;

                  if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_CLIPDIST) {
                     info->num_written_clipdistance += util_bitcount(fulldecl->Declaration.UsageMask);
                  }
                  if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_CULLDIST) {
                     info->num_written_culldistance += util_bitcount(fulldecl->Declaration.UsageMask);
                  }
                  /* extra info for special outputs */
                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
                        info->writes_z = TRUE;
                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_STENCIL)
                        info->writes_stencil = TRUE;
                  if (procType == TGSI_PROCESSOR_VERTEX &&
                      fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
                     info->writes_edgeflag = TRUE;
                  }

                  if (procType == TGSI_PROCESSOR_GEOMETRY &&
                      fulldecl->Semantic.Name ==
                      TGSI_SEMANTIC_VIEWPORT_INDEX) {
                     info->writes_viewport_index = TRUE;
                  }
                  if (procType == TGSI_PROCESSOR_GEOMETRY &&
                      fulldecl->Semantic.Name ==
                      TGSI_SEMANTIC_LAYER) {
                     info->writes_layer = TRUE;
                  }
               }

             }
         }
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         {
            uint reg = info->immediate_count++;
            uint file = TGSI_FILE_IMMEDIATE;

            info->file_mask[file] |= (1 << reg);
            info->file_count[file]++;
            info->file_max[file] = MAX2(info->file_max[file], (int)reg);
         }
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         {
            const struct tgsi_full_property *fullprop
               = &parse.FullToken.FullProperty;

            info->properties[info->num_properties].name =
               fullprop->Property.PropertyName;
            memcpy(info->properties[info->num_properties].data,
                   fullprop->u, 8 * sizeof(unsigned));;

            ++info->num_properties;
         }
         break;

      default:
         assert( 0 );
      }
   }

   info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] ||
                      info->opcode_count[TGSI_OPCODE_KILP]);

   /* extract simple properties */
   for (i = 0; i < info->num_properties; ++i) {
      switch (info->properties[i].name) {
      case TGSI_PROPERTY_FS_COORD_ORIGIN:
         info->origin_lower_left = info->properties[i].data[0];
         break;
      case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
         info->pixel_center_integer = info->properties[i].data[0];
         break;
      case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
         info->color0_writes_all_cbufs = info->properties[i].data[0];
         break;
      case TGSI_PROPERTY_GS_INPUT_PRIM:
         /* The dimensions of the IN decleration in geometry shader have
          * to be deduced from the type of the input primitive.
          */
         if (procType == TGSI_PROCESSOR_GEOMETRY) {
            unsigned input_primitive = info->properties[i].data[0];
            int num_verts = u_vertices_per_prim(input_primitive);
            unsigned j;
            info->file_count[TGSI_FILE_INPUT] = num_verts;
            info->file_max[TGSI_FILE_INPUT] =
               MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
            for (j = 0; j < num_verts; ++j) {
               info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
            }
         }
         break;
      default:
         ;
      }
   }

   tgsi_parse_free (&parse);
}
Exemple #22
0
unsigned
util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file)
{
   struct tgsi_shader_info info;
   struct tgsi_parse_context parse;
   unsigned count = 0;
   ubyte *semantic_name;
   ubyte *semantic_index;

   tgsi_scan_shader(tokens, &info);

   if(file == TGSI_FILE_INPUT)
   {
      semantic_name = info.input_semantic_name;
      semantic_index = info.input_semantic_index;
   }
   else if(file == TGSI_FILE_OUTPUT)
   {
      semantic_name = info.output_semantic_name;
      semantic_index = info.output_semantic_index;
   }
   else
   {
      assert(0);
      semantic_name = NULL;
      semantic_index = NULL;
   }

   tgsi_parse_init(&parse, tokens);

   memset(set->masks, 0, sizeof(set->masks));
   while(!tgsi_parse_end_of_tokens(&parse))
   {
      tgsi_parse_token(&parse);

      if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION)
      {
	 const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction;
	 unsigned i;
	 for(i = 0; i < finst->Instruction.NumDstRegs; ++i)
	 {
	    if(finst->Dst[i].Register.File == file)
	    {
	       unsigned idx = finst->Dst[i].Register.Index;
	       if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
	       {
		  if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
		     ++count;
	       }
	    }
	 }

	 for(i = 0; i < finst->Instruction.NumSrcRegs; ++i)
	 {
	    if(finst->Src[i].Register.File == file)
	    {
	       unsigned idx = finst->Src[i].Register.Index;
	       if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
	       {
		  if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
		     ++count;
	       }
	    }
	 }
      }
   }
   tgsi_parse_free(&parse);

   return count;
}
Exemple #23
0
static unsigned
compile_init(struct fd2_compile_context *ctx, struct fd_program_stateobj *prog,
		struct fd2_shader_stateobj *so)
{
	unsigned ret;

	ctx->prog = prog;
	ctx->so = so;
	ctx->cf = NULL;
	ctx->pred_depth = 0;

	ret = tgsi_parse_init(&ctx->parser, so->tokens);
	if (ret != TGSI_PARSE_OK)
		return ret;

	ctx->type = ctx->parser.FullHeader.Processor.Processor;
	ctx->position = ~0;
	ctx->psize = ~0;
	ctx->num_position = 0;
	ctx->num_param = 0;
	ctx->need_sync = 0;
	ctx->immediate_idx = 0;
	ctx->pred_reg = -1;
	ctx->num_internal_temps = 0;

	memset(ctx->num_regs, 0, sizeof(ctx->num_regs));
	memset(ctx->input_export_idx, 0, sizeof(ctx->input_export_idx));
	memset(ctx->output_export_idx, 0, sizeof(ctx->output_export_idx));

	/* do first pass to extract declarations: */
	while (!tgsi_parse_end_of_tokens(&ctx->parser)) {
		tgsi_parse_token(&ctx->parser);

		switch (ctx->parser.FullToken.Token.Type) {
		case TGSI_TOKEN_TYPE_DECLARATION: {
			struct tgsi_full_declaration *decl =
					&ctx->parser.FullToken.FullDeclaration;
			if (decl->Declaration.File == TGSI_FILE_OUTPUT) {
				unsigned name = decl->Semantic.Name;

				assert(decl->Declaration.Semantic);  // TODO is this ever not true?

				ctx->output_export_idx[decl->Range.First] =
						semantic_idx(&decl->Semantic);

				if (ctx->type == PIPE_SHADER_VERTEX) {
					switch (name) {
					case TGSI_SEMANTIC_POSITION:
						ctx->position = ctx->num_regs[TGSI_FILE_OUTPUT];
						ctx->num_position++;
						break;
					case TGSI_SEMANTIC_PSIZE:
						ctx->psize = ctx->num_regs[TGSI_FILE_OUTPUT];
						ctx->num_position++;
						break;
					case TGSI_SEMANTIC_COLOR:
					case TGSI_SEMANTIC_GENERIC:
						ctx->num_param++;
						break;
					default:
						DBG("unknown VS semantic name: %s",
								tgsi_semantic_names[name]);
						assert(0);
					}
				} else {
					switch (name) {
					case TGSI_SEMANTIC_COLOR:
					case TGSI_SEMANTIC_GENERIC:
						ctx->num_param++;
						break;
					default:
						DBG("unknown PS semantic name: %s",
								tgsi_semantic_names[name]);
						assert(0);
					}
				}
			} else if (decl->Declaration.File == TGSI_FILE_INPUT) {
				ctx->input_export_idx[decl->Range.First] =
						semantic_idx(&decl->Semantic);
			}
			ctx->num_regs[decl->Declaration.File] =
					MAX2(ctx->num_regs[decl->Declaration.File], decl->Range.Last + 1);
			break;
		}
		case TGSI_TOKEN_TYPE_IMMEDIATE: {
			struct tgsi_full_immediate *imm =
					&ctx->parser.FullToken.FullImmediate;
			unsigned n = ctx->so->num_immediates++;
			memcpy(ctx->so->immediates[n].val, imm->u, 16);
			break;
		}
		default:
			break;
		}
	}

	/* TGSI generated immediates are always entire vec4's, ones we
	 * generate internally are not:
	 */
	ctx->immediate_idx = ctx->so->num_immediates * 4;

	ctx->so->first_immediate = ctx->num_regs[TGSI_FILE_CONSTANT];

	tgsi_parse_free(&ctx->parser);

	return tgsi_parse_init(&ctx->parser, so->tokens);
}
Exemple #24
0
/**
 * Scan the given TGSI shader to collect information such as number of
 * registers used, special instructions used, etc.
 * \return info  the result of the scan
 */
void
tgsi_scan_shader(const struct tgsi_token *tokens,
                 struct tgsi_shader_info *info)
{
   uint procType, i;
   struct tgsi_parse_context parse;
   unsigned current_depth = 0;

   memset(info, 0, sizeof(*info));
   for (i = 0; i < TGSI_FILE_COUNT; i++)
      info->file_max[i] = -1;
   for (i = 0; i < Elements(info->const_file_max); i++)
      info->const_file_max[i] = -1;
   info->properties[TGSI_PROPERTY_GS_INVOCATIONS] = 1;

   /**
    ** Setup to begin parsing input shader
    **/
   if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
      debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
      return;
   }
   procType = parse.FullHeader.Processor.Processor;
   assert(procType == TGSI_PROCESSOR_FRAGMENT ||
          procType == TGSI_PROCESSOR_VERTEX ||
          procType == TGSI_PROCESSOR_GEOMETRY ||
          procType == TGSI_PROCESSOR_TESS_CTRL ||
          procType == TGSI_PROCESSOR_TESS_EVAL ||
          procType == TGSI_PROCESSOR_COMPUTE);
   info->processor = procType;


   /**
    ** Loop over incoming program tokens/instructions
    */
   while( !tgsi_parse_end_of_tokens( &parse ) ) {

      info->num_tokens++;

      tgsi_parse_token( &parse );

      switch( parse.FullToken.Token.Type ) {
      case TGSI_TOKEN_TYPE_INSTRUCTION:
         {
            const struct tgsi_full_instruction *fullinst
               = &parse.FullToken.FullInstruction;
            uint i;

            assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
            info->opcode_count[fullinst->Instruction.Opcode]++;

            switch (fullinst->Instruction.Opcode) {
            case TGSI_OPCODE_IF:
            case TGSI_OPCODE_UIF:
            case TGSI_OPCODE_BGNLOOP:
               current_depth++;
               info->max_depth = MAX2(info->max_depth, current_depth);
               break;
            case TGSI_OPCODE_ENDIF:
            case TGSI_OPCODE_ENDLOOP:
               current_depth--;
               break;
            default:
               break;
            }

            if (fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_CENTROID ||
                fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET ||
                fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) {
               const struct tgsi_full_src_register *src0 = &fullinst->Src[0];
               unsigned input;

               if (src0->Register.Indirect && src0->Indirect.ArrayID)
                  input = info->input_array_first[src0->Indirect.ArrayID];
               else
                  input = src0->Register.Index;

               /* For the INTERP opcodes, the interpolation is always
                * PERSPECTIVE unless LINEAR is specified.
                */
               switch (info->input_interpolate[input]) {
               case TGSI_INTERPOLATE_COLOR:
               case TGSI_INTERPOLATE_CONSTANT:
               case TGSI_INTERPOLATE_PERSPECTIVE:
                  switch (fullinst->Instruction.Opcode) {
                  case TGSI_OPCODE_INTERP_CENTROID:
                     info->uses_persp_opcode_interp_centroid = true;
                     break;
                  case TGSI_OPCODE_INTERP_OFFSET:
                     info->uses_persp_opcode_interp_offset = true;
                     break;
                  case TGSI_OPCODE_INTERP_SAMPLE:
                     info->uses_persp_opcode_interp_sample = true;
                     break;
                  }
                  break;

               case TGSI_INTERPOLATE_LINEAR:
                  switch (fullinst->Instruction.Opcode) {
                  case TGSI_OPCODE_INTERP_CENTROID:
                     info->uses_linear_opcode_interp_centroid = true;
                     break;
                  case TGSI_OPCODE_INTERP_OFFSET:
                     info->uses_linear_opcode_interp_offset = true;
                     break;
                  case TGSI_OPCODE_INTERP_SAMPLE:
                     info->uses_linear_opcode_interp_sample = true;
                     break;
                  }
                  break;
               }
            }

            if (fullinst->Instruction.Opcode >= TGSI_OPCODE_F2D &&
                fullinst->Instruction.Opcode <= TGSI_OPCODE_DSSG)
               info->uses_doubles = true;

            for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
               const struct tgsi_full_src_register *src =
                  &fullinst->Src[i];
               int ind = src->Register.Index;

               /* Mark which inputs are effectively used */
               if (src->Register.File == TGSI_FILE_INPUT) {
                  unsigned usage_mask;
                  usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
                  if (src->Register.Indirect) {
                     for (ind = 0; ind < info->num_inputs; ++ind) {
                        info->input_usage_mask[ind] |= usage_mask;
                     }
                  } else {
                     assert(ind >= 0);
                     assert(ind < PIPE_MAX_SHADER_INPUTS);
                     info->input_usage_mask[ind] |= usage_mask;
                  }

                  if (procType == TGSI_PROCESSOR_FRAGMENT &&
                      !src->Register.Indirect) {
                     unsigned name =
                        info->input_semantic_name[src->Register.Index];
                     unsigned index =
                        info->input_semantic_index[src->Register.Index];

                     if (name == TGSI_SEMANTIC_POSITION &&
                         (src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
                          src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
                          src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
                          src->Register.SwizzleW == TGSI_SWIZZLE_Z))
                        info->reads_z = TRUE;

                     if (name == TGSI_SEMANTIC_COLOR) {
                        unsigned mask =
                              (1 << src->Register.SwizzleX) |
                              (1 << src->Register.SwizzleY) |
                              (1 << src->Register.SwizzleZ) |
                              (1 << src->Register.SwizzleW);

                        info->colors_read |= mask << (index * 4);
                     }
                  }
               }

               /* check for indirect register reads */
               if (src->Register.Indirect) {
                  info->indirect_files |= (1 << src->Register.File);
                  info->indirect_files_read |= (1 << src->Register.File);
               }

               /* MSAA samplers */
               if (src->Register.File == TGSI_FILE_SAMPLER) {
                  assert(fullinst->Instruction.Texture);
                  assert(src->Register.Index < Elements(info->is_msaa_sampler));

                  if (fullinst->Instruction.Texture &&
                      (fullinst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ||
                       fullinst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA)) {
                     info->is_msaa_sampler[src->Register.Index] = TRUE;
                  }
               }
            }

            /* check for indirect register writes */
            for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
               const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
               if (dst->Register.Indirect) {
                  info->indirect_files |= (1 << dst->Register.File);
                  info->indirect_files_written |= (1 << dst->Register.File);
               }
            }

            info->num_instructions++;
         }
         break;

      case TGSI_TOKEN_TYPE_DECLARATION:
         {
            const struct tgsi_full_declaration *fulldecl
               = &parse.FullToken.FullDeclaration;
            const uint file = fulldecl->Declaration.File;
            uint reg;

            if (fulldecl->Declaration.Array) {
               unsigned array_id = fulldecl->Array.ArrayID;

               switch (file) {
               case TGSI_FILE_INPUT:
                  assert(array_id < ARRAY_SIZE(info->input_array_first));
                  info->input_array_first[array_id] = fulldecl->Range.First;
                  info->input_array_last[array_id] = fulldecl->Range.Last;
                  break;
               case TGSI_FILE_OUTPUT:
                  assert(array_id < ARRAY_SIZE(info->output_array_first));
                  info->output_array_first[array_id] = fulldecl->Range.First;
                  info->output_array_last[array_id] = fulldecl->Range.Last;
                  break;
               }
               info->array_max[file] = MAX2(info->array_max[file], array_id);
            }

            for (reg = fulldecl->Range.First;
                 reg <= fulldecl->Range.Last;
                 reg++) {
               unsigned semName = fulldecl->Semantic.Name;
               unsigned semIndex =
                  fulldecl->Semantic.Index + (reg - fulldecl->Range.First);

               /* only first 32 regs will appear in this bitfield */
               info->file_mask[file] |= (1 << reg);
               info->file_count[file]++;
               info->file_max[file] = MAX2(info->file_max[file], (int)reg);

               if (file == TGSI_FILE_CONSTANT) {
                  int buffer = 0;

                  if (fulldecl->Declaration.Dimension)
                     buffer = fulldecl->Dim.Index2D;

                  info->const_file_max[buffer] =
                        MAX2(info->const_file_max[buffer], (int)reg);
               }
               else if (file == TGSI_FILE_INPUT) {
                  info->input_semantic_name[reg] = (ubyte) semName;
                  info->input_semantic_index[reg] = (ubyte) semIndex;
                  info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
                  info->input_interpolate_loc[reg] = (ubyte)fulldecl->Interp.Location;
                  info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
                  info->num_inputs++;

                  /* Only interpolated varyings. Don't include POSITION.
                   * Don't include integer varyings, because they are not
                   * interpolated.
                   */
                  if (semName == TGSI_SEMANTIC_GENERIC ||
                      semName == TGSI_SEMANTIC_TEXCOORD ||
                      semName == TGSI_SEMANTIC_COLOR ||
                      semName == TGSI_SEMANTIC_BCOLOR ||
                      semName == TGSI_SEMANTIC_FOG ||
                      semName == TGSI_SEMANTIC_CLIPDIST ||
                      semName == TGSI_SEMANTIC_CULLDIST) {
                     switch (fulldecl->Interp.Interpolate) {
                     case TGSI_INTERPOLATE_COLOR:
                     case TGSI_INTERPOLATE_PERSPECTIVE:
                        switch (fulldecl->Interp.Location) {
                        case TGSI_INTERPOLATE_LOC_CENTER:
                           info->uses_persp_center = true;
                           break;
                        case TGSI_INTERPOLATE_LOC_CENTROID:
                           info->uses_persp_centroid = true;
                           break;
                        case TGSI_INTERPOLATE_LOC_SAMPLE:
                           info->uses_persp_sample = true;
                           break;
                        }
                        break;
                     case TGSI_INTERPOLATE_LINEAR:
                        switch (fulldecl->Interp.Location) {
                        case TGSI_INTERPOLATE_LOC_CENTER:
                           info->uses_linear_center = true;
                           break;
                        case TGSI_INTERPOLATE_LOC_CENTROID:
                           info->uses_linear_centroid = true;
                           break;
                        case TGSI_INTERPOLATE_LOC_SAMPLE:
                           info->uses_linear_sample = true;
                           break;
                        }
                        break;
                     /* TGSI_INTERPOLATE_CONSTANT doesn't do any interpolation. */
                     }
                  }

                  if (semName == TGSI_SEMANTIC_PRIMID)
                     info->uses_primid = TRUE;
                  else if (procType == TGSI_PROCESSOR_FRAGMENT) {
                     if (semName == TGSI_SEMANTIC_POSITION)
                        info->reads_position = TRUE;
                     else if (semName == TGSI_SEMANTIC_FACE)
                        info->uses_frontface = TRUE;
                  }
               }
               else if (file == TGSI_FILE_SYSTEM_VALUE) {
                  unsigned index = fulldecl->Range.First;

                  info->system_value_semantic_name[index] = semName;
                  info->num_system_values = MAX2(info->num_system_values,
                                                 index + 1);

                  if (semName == TGSI_SEMANTIC_INSTANCEID) {
                     info->uses_instanceid = TRUE;
                  }
                  else if (semName == TGSI_SEMANTIC_VERTEXID) {
                     info->uses_vertexid = TRUE;
                  }
                  else if (semName == TGSI_SEMANTIC_VERTEXID_NOBASE) {
                     info->uses_vertexid_nobase = TRUE;
                  }
                  else if (semName == TGSI_SEMANTIC_BASEVERTEX) {
                     info->uses_basevertex = TRUE;
                  }
                  else if (semName == TGSI_SEMANTIC_PRIMID) {
                     info->uses_primid = TRUE;
                  } else if (semName == TGSI_SEMANTIC_INVOCATIONID) {
                     info->uses_invocationid = TRUE;
                  }
               }
               else if (file == TGSI_FILE_OUTPUT) {
                  info->output_semantic_name[reg] = (ubyte) semName;
                  info->output_semantic_index[reg] = (ubyte) semIndex;
                  info->num_outputs++;

                  if (semName == TGSI_SEMANTIC_COLOR)
                     info->colors_written |= 1 << semIndex;

                  if (procType == TGSI_PROCESSOR_VERTEX ||
                      procType == TGSI_PROCESSOR_GEOMETRY ||
                      procType == TGSI_PROCESSOR_TESS_CTRL ||
                      procType == TGSI_PROCESSOR_TESS_EVAL) {
                     if (semName == TGSI_SEMANTIC_VIEWPORT_INDEX) {
                        info->writes_viewport_index = TRUE;
                     }
                     else if (semName == TGSI_SEMANTIC_LAYER) {
                        info->writes_layer = TRUE;
                     }
                     else if (semName == TGSI_SEMANTIC_PSIZE) {
                        info->writes_psize = TRUE;
                     }
                     else if (semName == TGSI_SEMANTIC_CLIPVERTEX) {
                        info->writes_clipvertex = TRUE;
                     }
                  }

                  if (procType == TGSI_PROCESSOR_FRAGMENT) {
                     if (semName == TGSI_SEMANTIC_POSITION) {
                        info->writes_z = TRUE;
                     }
                     else if (semName == TGSI_SEMANTIC_STENCIL) {
                        info->writes_stencil = TRUE;
                     } else if (semName == TGSI_SEMANTIC_SAMPLEMASK) {
                        info->writes_samplemask = TRUE;
                     }
                  }

                  if (procType == TGSI_PROCESSOR_VERTEX) {
                     if (semName == TGSI_SEMANTIC_EDGEFLAG) {
                        info->writes_edgeflag = TRUE;
                     }
                  }
               } else if (file == TGSI_FILE_SAMPLER) {
                  info->samplers_declared |= 1 << reg;
               }
            }
         }
         break;

      case TGSI_TOKEN_TYPE_IMMEDIATE:
         {
            uint reg = info->immediate_count++;
            uint file = TGSI_FILE_IMMEDIATE;

            info->file_mask[file] |= (1 << reg);
            info->file_count[file]++;
            info->file_max[file] = MAX2(info->file_max[file], (int)reg);
         }
         break;

      case TGSI_TOKEN_TYPE_PROPERTY:
         {
            const struct tgsi_full_property *fullprop
               = &parse.FullToken.FullProperty;
            unsigned name = fullprop->Property.PropertyName;
            unsigned value = fullprop->u[0].Data;

            assert(name < Elements(info->properties));
            info->properties[name] = value;

            switch (name) {
            case TGSI_PROPERTY_NUM_CLIPDIST_ENABLED:
               info->num_written_clipdistance = value;
               info->clipdist_writemask |= (1 << value) - 1;
               break;
            case TGSI_PROPERTY_NUM_CULLDIST_ENABLED:
               info->num_written_culldistance = value;
               info->culldist_writemask |= (1 << value) - 1;
               break;
            }
         }
         break;

      default:
         assert( 0 );
      }
   }

   info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] ||
                      info->opcode_count[TGSI_OPCODE_KILL]);

   /* The dimensions of the IN decleration in geometry shader have
    * to be deduced from the type of the input primitive.
    */
   if (procType == TGSI_PROCESSOR_GEOMETRY) {
      unsigned input_primitive =
            info->properties[TGSI_PROPERTY_GS_INPUT_PRIM];
      int num_verts = u_vertices_per_prim(input_primitive);
      int j;
      info->file_count[TGSI_FILE_INPUT] = num_verts;
      info->file_max[TGSI_FILE_INPUT] =
            MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
      for (j = 0; j < num_verts; ++j) {
         info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
      }
   }

   tgsi_parse_free (&parse);
}