allows one to specify a safe (bound checked) array filled with immediates. it works just like a const array and declares much like our current immediates.tags/mesa-7.9-rc1
| @@ -164,6 +164,7 @@ tgsi_default_full_declaration( void ) | |||
| full_declaration.Declaration = tgsi_default_declaration(); | |||
| full_declaration.Range = tgsi_default_declaration_range(); | |||
| full_declaration.Semantic = tgsi_default_declaration_semantic(); | |||
| full_declaration.ImmediateData.u = NULL; | |||
| return full_declaration; | |||
| } | |||
| @@ -180,7 +181,7 @@ tgsi_build_full_declaration( | |||
| struct tgsi_declaration_range *dr; | |||
| if( maxsize <= size ) | |||
| return 0; | |||
| return 0; | |||
| declaration = (struct tgsi_declaration *) &tokens[size]; | |||
| size++; | |||
| @@ -235,6 +236,24 @@ tgsi_build_full_declaration( | |||
| header ); | |||
| } | |||
| if (full_decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) { | |||
| unsigned i, j; | |||
| union tgsi_immediate_data *data; | |||
| for (i = 0; i <= dr->Last; ++i) { | |||
| for (j = 0; j < 4; ++j) { | |||
| unsigned idx = i*4 + j; | |||
| if (maxsize <= size) | |||
| return 0; | |||
| data = (union tgsi_immediate_data *) &tokens[size]; | |||
| ++size; | |||
| *data = full_decl->ImmediateData.u[idx]; | |||
| declaration_grow( declaration, header ); | |||
| } | |||
| } | |||
| } | |||
| return size; | |||
| } | |||
| @@ -101,7 +101,8 @@ static const char *file_names[TGSI_FILE_COUNT] = | |||
| "ADDR", | |||
| "IMM", | |||
| "PRED", | |||
| "SV" | |||
| "SV", | |||
| "IMMX" | |||
| }; | |||
| static const char *interpolate_names[] = | |||
| @@ -292,6 +293,39 @@ _dump_writemask( | |||
| } | |||
| } | |||
| static void | |||
| dump_imm_data(struct tgsi_iterate_context *iter, | |||
| union tgsi_immediate_data *data, | |||
| unsigned num_tokens, | |||
| unsigned data_type) | |||
| { | |||
| struct dump_ctx *ctx = (struct dump_ctx *)iter; | |||
| unsigned i ; | |||
| TXT( " {" ); | |||
| assert( num_tokens <= 4 ); | |||
| for (i = 0; i < num_tokens; i++) { | |||
| switch (data_type) { | |||
| case TGSI_IMM_FLOAT32: | |||
| FLT( data[i].Float ); | |||
| break; | |||
| case TGSI_IMM_UINT32: | |||
| UID(data[i].Uint); | |||
| break; | |||
| case TGSI_IMM_INT32: | |||
| SID(data[i].Int); | |||
| break; | |||
| default: | |||
| assert( 0 ); | |||
| } | |||
| if (i < num_tokens - 1) | |||
| TXT( ", " ); | |||
| } | |||
| TXT( "}" ); | |||
| } | |||
| static boolean | |||
| iter_declaration( | |||
| struct tgsi_iterate_context *iter, | |||
| @@ -372,6 +406,43 @@ iter_declaration( | |||
| } | |||
| } | |||
| if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) { | |||
| unsigned i; | |||
| char range_indent[4]; | |||
| TXT(" {"); | |||
| if (decl->Range.Last < 10) | |||
| range_indent[0] = '\0'; | |||
| else if (decl->Range.Last < 100) { | |||
| range_indent[0] = ' '; | |||
| range_indent[1] = '\0'; | |||
| } else if (decl->Range.Last < 1000) { | |||
| range_indent[0] = ' '; | |||
| range_indent[1] = ' '; | |||
| range_indent[2] = '\0'; | |||
| } else { | |||
| range_indent[0] = ' '; | |||
| range_indent[1] = ' '; | |||
| range_indent[2] = ' '; | |||
| range_indent[3] = '\0'; | |||
| } | |||
| dump_imm_data(iter, decl->ImmediateData.u, | |||
| 4, TGSI_IMM_FLOAT32); | |||
| for(i = 1; i <= decl->Range.Last; ++i) { | |||
| /* indent by strlen of: | |||
| * "DCL IMMX[0..1] {" */ | |||
| CHR('\n'); | |||
| TXT( " " ); | |||
| TXT( range_indent ); | |||
| dump_imm_data(iter, decl->ImmediateData.u + i, | |||
| 4, TGSI_IMM_FLOAT32); | |||
| } | |||
| TXT(" }"); | |||
| } | |||
| EOL(); | |||
| return TRUE; | |||
| @@ -445,33 +516,11 @@ iter_immediate( | |||
| { | |||
| struct dump_ctx *ctx = (struct dump_ctx *) iter; | |||
| uint i; | |||
| TXT( "IMM " ); | |||
| ENM( imm->Immediate.DataType, immediate_type_names ); | |||
| TXT( " { " ); | |||
| assert( imm->Immediate.NrTokens <= 4 + 1 ); | |||
| for (i = 0; i < imm->Immediate.NrTokens - 1; i++) { | |||
| switch (imm->Immediate.DataType) { | |||
| case TGSI_IMM_FLOAT32: | |||
| FLT( imm->u[i].Float ); | |||
| break; | |||
| case TGSI_IMM_UINT32: | |||
| UID(imm->u[i].Uint); | |||
| break; | |||
| case TGSI_IMM_INT32: | |||
| SID(imm->u[i].Int); | |||
| break; | |||
| default: | |||
| assert( 0 ); | |||
| } | |||
| if (i < imm->Immediate.NrTokens - 2) | |||
| TXT( ", " ); | |||
| } | |||
| TXT( " }" ); | |||
| dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1, | |||
| imm->Immediate.DataType); | |||
| EOL(); | |||
| @@ -502,12 +551,12 @@ iter_instruction( | |||
| INSTID( instno ); | |||
| TXT( ": " ); | |||
| ctx->indent -= info->pre_dedent; | |||
| for(i = 0; (int)i < ctx->indent; ++i) | |||
| TXT( " " ); | |||
| ctx->indent += info->post_indent; | |||
| if (inst->Instruction.Predicate) { | |||
| CHR( '(' ); | |||
| @@ -699,6 +699,19 @@ tgsi_exec_machine_bind_shader( | |||
| ++mach->NumOutputs; | |||
| } | |||
| } | |||
| if (parse.FullToken.FullDeclaration.Declaration.File == | |||
| TGSI_FILE_IMMEDIATE_ARRAY) { | |||
| unsigned reg; | |||
| struct tgsi_full_declaration *decl = | |||
| &parse.FullToken.FullDeclaration; | |||
| debug_assert(decl->Range.Last < TGSI_EXEC_NUM_IMMEDIATES); | |||
| for (reg = decl->Range.First; reg <= decl->Range.Last; ++reg) { | |||
| for( i = 0; i < 4; i++ ) { | |||
| int idx = reg * 4 + i; | |||
| mach->ImmArray[reg][i] = decl->ImmediateData.u[idx].Float; | |||
| } | |||
| } | |||
| } | |||
| memcpy(declarations + numDeclarations, | |||
| &parse.FullToken.FullDeclaration, | |||
| sizeof(declarations[0])); | |||
| @@ -1074,6 +1087,14 @@ fetch_src_file_channel(const struct tgsi_exec_machine *mach, | |||
| } | |||
| break; | |||
| case TGSI_FILE_IMMEDIATE_ARRAY: | |||
| for (i = 0; i < QUAD_SIZE; i++) { | |||
| assert(index2D->i[i] == 0); | |||
| chan->f[i] = mach->ImmArray[index->i[i]][swizzle]; | |||
| } | |||
| break; | |||
| case TGSI_FILE_ADDRESS: | |||
| for (i = 0; i < QUAD_SIZE; i++) { | |||
| assert(index->i[i] >= 0); | |||
| @@ -240,6 +240,8 @@ struct tgsi_exec_machine | |||
| float Imms[TGSI_EXEC_NUM_IMMEDIATES][4]; | |||
| float ImmArray[TGSI_EXEC_NUM_IMMEDIATES][4]; | |||
| struct tgsi_exec_vector Inputs[TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS]; | |||
| struct tgsi_exec_vector Outputs[TGSI_MAX_TOTAL_VERTICES]; | |||
| @@ -117,6 +117,17 @@ tgsi_parse_token( | |||
| next_token( ctx, &decl->Semantic ); | |||
| } | |||
| if (decl->Declaration.File == TGSI_FILE_IMMEDIATE_ARRAY) { | |||
| unsigned i, j; | |||
| decl->ImmediateData.u = (union tgsi_immediate_data*) | |||
| &ctx->Tokens[ctx->Position]; | |||
| for (i = 0; i <= decl->Range.Last; ++i) { | |||
| for (j = 0; j < 4; ++j) { | |||
| ctx->Position++; | |||
| } | |||
| } | |||
| } | |||
| break; | |||
| } | |||
| @@ -54,12 +54,18 @@ struct tgsi_full_src_register | |||
| struct tgsi_src_register DimIndirect; | |||
| }; | |||
| struct tgsi_immediate_array_data | |||
| { | |||
| union tgsi_immediate_data *u; | |||
| }; | |||
| struct tgsi_full_declaration | |||
| { | |||
| struct tgsi_declaration Declaration; | |||
| struct tgsi_declaration_range Range; | |||
| struct tgsi_declaration_dimension Dim; | |||
| struct tgsi_declaration_semantic Semantic; | |||
| struct tgsi_immediate_array_data ImmediateData; | |||
| }; | |||
| struct tgsi_full_immediate | |||
| @@ -235,7 +235,8 @@ static const char *file_names[TGSI_FILE_COUNT] = | |||
| "ADDR", | |||
| "IMM", | |||
| "PRED", | |||
| "SV" | |||
| "SV", | |||
| "IMMX" | |||
| }; | |||
| static boolean | |||
| @@ -280,7 +280,8 @@ static const char *file_names[TGSI_FILE_COUNT] = | |||
| "ADDR", | |||
| "IMM", | |||
| "PRED", | |||
| "SV" | |||
| "SV", | |||
| "IMMX" | |||
| }; | |||
| static boolean | |||
| @@ -985,6 +986,45 @@ static const char *interpolate_names[TGSI_INTERPOLATE_COUNT] = | |||
| "PERSPECTIVE" | |||
| }; | |||
| /* parses a 4-touple of the form {x, y, z, w} | |||
| * where x, y, z, w are numbers */ | |||
| static boolean parse_immediate_data(struct translate_ctx *ctx, | |||
| float *values) | |||
| { | |||
| unsigned i; | |||
| eat_opt_white( &ctx->cur ); | |||
| if (*ctx->cur != '{') { | |||
| report_error( ctx, "Expected `{'" ); | |||
| return FALSE; | |||
| } | |||
| ctx->cur++; | |||
| for (i = 0; i < 4; i++) { | |||
| eat_opt_white( &ctx->cur ); | |||
| if (i > 0) { | |||
| if (*ctx->cur != ',') { | |||
| report_error( ctx, "Expected `,'" ); | |||
| return FALSE; | |||
| } | |||
| ctx->cur++; | |||
| eat_opt_white( &ctx->cur ); | |||
| } | |||
| if (!parse_float( &ctx->cur, &values[i] )) { | |||
| report_error( ctx, "Expected literal floating point" ); | |||
| return FALSE; | |||
| } | |||
| } | |||
| eat_opt_white( &ctx->cur ); | |||
| if (*ctx->cur != '}') { | |||
| report_error( ctx, "Expected `}'" ); | |||
| return FALSE; | |||
| } | |||
| ctx->cur++; | |||
| return TRUE; | |||
| } | |||
| static boolean parse_declaration( struct translate_ctx *ctx ) | |||
| { | |||
| struct tgsi_full_declaration decl; | |||
| @@ -995,6 +1035,7 @@ static boolean parse_declaration( struct translate_ctx *ctx ) | |||
| const char *cur; | |||
| uint advance; | |||
| boolean is_vs_input; | |||
| boolean is_imm_array; | |||
| assert(Elements(semantic_names) == TGSI_SEMANTIC_COUNT); | |||
| assert(Elements(interpolate_names) == TGSI_INTERPOLATE_COUNT); | |||
| @@ -1025,6 +1066,7 @@ static boolean parse_declaration( struct translate_ctx *ctx ) | |||
| is_vs_input = (file == TGSI_FILE_INPUT && | |||
| ctx->processor == TGSI_PROCESSOR_VERTEX); | |||
| is_imm_array = (file == TGSI_FILE_IMMEDIATE_ARRAY); | |||
| cur = ctx->cur; | |||
| eat_opt_white( &cur ); | |||
| @@ -1067,6 +1109,44 @@ static boolean parse_declaration( struct translate_ctx *ctx ) | |||
| break; | |||
| } | |||
| } | |||
| } else if (is_imm_array) { | |||
| unsigned i; | |||
| float *vals_itr; | |||
| /* we have our immediate data */ | |||
| if (*cur != '{') { | |||
| report_error( ctx, "Immediate array without data" ); | |||
| return FALSE; | |||
| } | |||
| ++cur; | |||
| ctx->cur = cur; | |||
| decl.ImmediateData.u = | |||
| MALLOC(sizeof(union tgsi_immediate_data) * 4 * | |||
| (decl.Range.Last + 1)); | |||
| vals_itr = (float*)decl.ImmediateData.u; | |||
| for (i = 0; i <= decl.Range.Last; ++i) { | |||
| if (!parse_immediate_data(ctx, vals_itr)) { | |||
| FREE(decl.ImmediateData.u); | |||
| return FALSE; | |||
| } | |||
| vals_itr += 4; | |||
| eat_opt_white( &ctx->cur ); | |||
| if (*ctx->cur != ',') { | |||
| if (i != decl.Range.Last) { | |||
| report_error( ctx, "Not enough data in immediate array!" ); | |||
| FREE(decl.ImmediateData.u); | |||
| return FALSE; | |||
| } | |||
| } else | |||
| ++ctx->cur; | |||
| } | |||
| eat_opt_white( &ctx->cur ); | |||
| if (*ctx->cur != '}') { | |||
| FREE(decl.ImmediateData.u); | |||
| report_error( ctx, "Immediate array data missing closing '}'" ); | |||
| return FALSE; | |||
| } | |||
| ++ctx->cur; | |||
| } | |||
| cur = ctx->cur; | |||
| @@ -1097,6 +1177,10 @@ static boolean parse_declaration( struct translate_ctx *ctx ) | |||
| ctx->tokens_cur, | |||
| ctx->header, | |||
| (uint) (ctx->tokens_end - ctx->tokens_cur) ); | |||
| if (is_imm_array) | |||
| FREE(decl.ImmediateData.u); | |||
| if (advance == 0) | |||
| return FALSE; | |||
| ctx->tokens_cur += advance; | |||
| @@ -1107,7 +1191,6 @@ static boolean parse_declaration( struct translate_ctx *ctx ) | |||
| static boolean parse_immediate( struct translate_ctx *ctx ) | |||
| { | |||
| struct tgsi_full_immediate imm; | |||
| uint i; | |||
| float values[4]; | |||
| uint advance; | |||
| @@ -1115,37 +1198,13 @@ static boolean parse_immediate( struct translate_ctx *ctx ) | |||
| report_error( ctx, "Syntax error" ); | |||
| return FALSE; | |||
| } | |||
| if (!str_match_no_case( &ctx->cur, "FLT32" ) || is_digit_alpha_underscore( ctx->cur )) { | |||
| if (!str_match_no_case( &ctx->cur, "FLT32" ) || | |||
| is_digit_alpha_underscore( ctx->cur )) { | |||
| report_error( ctx, "Expected `FLT32'" ); | |||
| return FALSE; | |||
| } | |||
| eat_opt_white( &ctx->cur ); | |||
| if (*ctx->cur != '{') { | |||
| report_error( ctx, "Expected `{'" ); | |||
| return FALSE; | |||
| } | |||
| ctx->cur++; | |||
| for (i = 0; i < 4; i++) { | |||
| eat_opt_white( &ctx->cur ); | |||
| if (i > 0) { | |||
| if (*ctx->cur != ',') { | |||
| report_error( ctx, "Expected `,'" ); | |||
| return FALSE; | |||
| } | |||
| ctx->cur++; | |||
| eat_opt_white( &ctx->cur ); | |||
| } | |||
| if (!parse_float( &ctx->cur, &values[i] )) { | |||
| report_error( ctx, "Expected literal floating point" ); | |||
| return FALSE; | |||
| } | |||
| } | |||
| eat_opt_white( &ctx->cur ); | |||
| if (*ctx->cur != '}') { | |||
| report_error( ctx, "Expected `}'" ); | |||
| return FALSE; | |||
| } | |||
| ctx->cur++; | |||
| parse_immediate_data(ctx, values); | |||
| imm = tgsi_default_full_immediate(); | |||
| imm.Immediate.NrTokens += 4; | |||
| @@ -65,16 +65,17 @@ struct tgsi_token | |||
| }; | |||
| enum tgsi_file_type { | |||
| TGSI_FILE_NULL =0, | |||
| TGSI_FILE_CONSTANT =1, | |||
| TGSI_FILE_INPUT =2, | |||
| TGSI_FILE_OUTPUT =3, | |||
| TGSI_FILE_TEMPORARY =4, | |||
| TGSI_FILE_SAMPLER =5, | |||
| TGSI_FILE_ADDRESS =6, | |||
| TGSI_FILE_IMMEDIATE =7, | |||
| TGSI_FILE_PREDICATE =8, | |||
| TGSI_FILE_SYSTEM_VALUE =9, | |||
| TGSI_FILE_NULL =0, | |||
| TGSI_FILE_CONSTANT =1, | |||
| TGSI_FILE_INPUT =2, | |||
| TGSI_FILE_OUTPUT =3, | |||
| TGSI_FILE_TEMPORARY =4, | |||
| TGSI_FILE_SAMPLER =5, | |||
| TGSI_FILE_ADDRESS =6, | |||
| TGSI_FILE_IMMEDIATE =7, | |||
| TGSI_FILE_PREDICATE =8, | |||
| TGSI_FILE_SYSTEM_VALUE =9, | |||
| TGSI_FILE_IMMEDIATE_ARRAY =10, | |||
| TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */ | |||
| }; | |||
| @@ -159,9 +160,9 @@ struct tgsi_declaration_semantic | |||
| struct tgsi_immediate | |||
| { | |||
| unsigned Type : 4; /**< TGSI_TOKEN_TYPE_IMMEDIATE */ | |||
| unsigned NrTokens : 8; /**< UINT */ | |||
| unsigned NrTokens : 14; /**< UINT */ | |||
| unsigned DataType : 4; /**< one of TGSI_IMM_x */ | |||
| unsigned Padding : 16; | |||
| unsigned Padding : 10; | |||
| }; | |||
| union tgsi_immediate_data | |||