static boolean parse_dst_operand( struct translate_ctx *ctx, struct tgsi_full_dst_register *dst ) { uint file; uint writemask; const char *cur; struct parsed_bracket bracket[2]; int parsed_opt_brackets; if (!parse_register_dst( ctx, &file, &bracket[0] )) return FALSE; if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets)) return FALSE; cur = ctx->cur; eat_opt_white( &cur ); if (!parse_opt_writemask( ctx, &writemask )) return FALSE; dst->Register.File = file; if (parsed_opt_brackets) { dst->Register.Dimension = 1; dst->Dimension.Indirect = 0; dst->Dimension.Dimension = 0; dst->Dimension.Index = bracket[0].index; if (bracket[0].ind_file != TGSI_FILE_NULL) { dst->Dimension.Indirect = 1; dst->DimIndirect.File = bracket[0].ind_file; dst->DimIndirect.Index = bracket[0].ind_index; dst->DimIndirect.Swizzle = bracket[0].ind_comp; dst->DimIndirect.ArrayID = bracket[0].ind_array; } bracket[0] = bracket[1]; } dst->Register.Index = bracket[0].index; dst->Register.WriteMask = writemask; if (bracket[0].ind_file != TGSI_FILE_NULL) { dst->Register.Indirect = 1; dst->Indirect.File = bracket[0].ind_file; dst->Indirect.Index = bracket[0].ind_index; dst->Indirect.Swizzle = bracket[0].ind_comp; dst->Indirect.ArrayID = bracket[0].ind_array; } return TRUE; }
static boolean parse_declaration( struct translate_ctx *ctx ) { struct tgsi_full_declaration decl; uint file; struct parsed_dcl_bracket brackets[2]; int num_brackets; uint writemask; const char *cur, *cur2; uint advance; boolean is_vs_input; if (!eat_white( &ctx->cur )) { report_error( ctx, "Syntax error" ); return FALSE; } if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) return FALSE; if (!parse_opt_writemask( ctx, &writemask )) return FALSE; decl = tgsi_default_full_declaration(); decl.Declaration.File = file; decl.Declaration.UsageMask = writemask; if (num_brackets == 1) { decl.Range.First = brackets[0].first; decl.Range.Last = brackets[0].last; } else { decl.Range.First = brackets[1].first; decl.Range.Last = brackets[1].last; decl.Declaration.Dimension = 1; decl.Dim.Index2D = brackets[0].first; } is_vs_input = (file == TGSI_FILE_INPUT && ctx->processor == TGSI_PROCESSOR_VERTEX); cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',') { cur2 = cur; cur2++; eat_opt_white( &cur2 ); if (str_match_nocase_whole( &cur2, "ARRAY" )) { int arrayid; if (*cur2 != '(') { report_error( ctx, "Expected `('" ); return FALSE; } cur2++; eat_opt_white( &cur2 ); if (!parse_int( &cur2, &arrayid )) { report_error( ctx, "Expected `,'" ); return FALSE; } eat_opt_white( &cur2 ); if (*cur2 != ')') { report_error( ctx, "Expected `)'" ); return FALSE; } cur2++; decl.Declaration.Array = 1; decl.Array.ArrayID = arrayid; ctx->cur = cur = cur2; } } if (*cur == ',' && !is_vs_input) { uint i, j; cur++; eat_opt_white( &cur ); if (file == TGSI_FILE_IMAGE) { for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { decl.Image.Resource = i; break; } } if (i == TGSI_TEXTURE_COUNT) { report_error(ctx, "Expected texture target"); return FALSE; } cur2 = cur; eat_opt_white(&cur2); while (*cur2 == ',') { cur2++; eat_opt_white(&cur2); if (str_match_nocase_whole(&cur2, "RAW")) { decl.Image.Raw = 1; } else if (str_match_nocase_whole(&cur2, "WR")) { decl.Image.Writable = 1; } else { for (i = 0; i < PIPE_FORMAT_COUNT; i++) { const struct util_format_description *desc = util_format_description(i); if (desc && str_match_nocase_whole(&cur2, desc->name)) { decl.Image.Format = i; break; } } if (i == PIPE_FORMAT_COUNT) break; } cur = cur2; eat_opt_white(&cur2); } ctx->cur = cur; } else if (file == TGSI_FILE_SAMPLER_VIEW) { for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) { decl.SamplerView.Resource = i; break; } } if (i == TGSI_TEXTURE_COUNT) { report_error(ctx, "Expected texture target"); return FALSE; } eat_opt_white( &cur ); if (*cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ++cur; eat_opt_white( &cur ); for (j = 0; j < 4; ++j) { for (i = 0; i < TGSI_RETURN_TYPE_COUNT; ++i) { if (str_match_nocase_whole(&cur, tgsi_return_type_names[i])) { switch (j) { case 0: decl.SamplerView.ReturnTypeX = i; break; case 1: decl.SamplerView.ReturnTypeY = i; break; case 2: decl.SamplerView.ReturnTypeZ = i; break; case 3: decl.SamplerView.ReturnTypeW = i; break; default: assert(0); } break; } } if (i == TGSI_RETURN_TYPE_COUNT) { if (j == 0 || j > 2) { report_error(ctx, "Expected type name"); return FALSE; } break; } else { cur2 = cur; eat_opt_white( &cur2 ); if (*cur2 == ',') { cur2++; eat_opt_white( &cur2 ); cur = cur2; continue; } else break; } } if (j < 4) { decl.SamplerView.ReturnTypeY = decl.SamplerView.ReturnTypeZ = decl.SamplerView.ReturnTypeW = decl.SamplerView.ReturnTypeX; } ctx->cur = cur; } else if (file == TGSI_FILE_BUFFER) { if (str_match_nocase_whole(&cur, "ATOMIC")) { decl.Declaration.Atomic = 1; ctx->cur = cur; } } else if (file == TGSI_FILE_MEMORY) { if (str_match_nocase_whole(&cur, "SHARED")) { decl.Declaration.Shared = 1; ctx->cur = cur; } } else { if (str_match_nocase_whole(&cur, "LOCAL")) { decl.Declaration.Local = 1; ctx->cur = cur; } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',') { cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) { uint index; cur2 = cur; eat_opt_white( &cur2 ); if (*cur2 == '[') { cur2++; eat_opt_white( &cur2 ); if (!parse_uint( &cur2, &index )) { report_error( ctx, "Expected literal integer" ); return FALSE; } eat_opt_white( &cur2 ); if (*cur2 != ']') { report_error( ctx, "Expected `]'" ); return FALSE; } cur2++; decl.Semantic.Index = index; cur = cur2; } decl.Declaration.Semantic = 1; decl.Semantic.Name = i; ctx->cur = cur; break; } } } } } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) { decl.Declaration.Interpolate = 1; decl.Interp.Interpolate = i; ctx->cur = cur; break; } } if (i == TGSI_INTERPOLATE_COUNT) { report_error( ctx, "Expected semantic or interpolate attribute" ); return FALSE; } } cur = ctx->cur; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_INTERPOLATE_LOC_COUNT; i++) { if (str_match_nocase_whole( &cur, tgsi_interpolate_locations[i] )) { decl.Interp.Location = i; ctx->cur = cur; break; } } } advance = tgsi_build_full_declaration( &decl, ctx->tokens_cur, ctx->header, (uint) (ctx->tokens_end - ctx->tokens_cur) ); if (advance == 0) return FALSE; ctx->tokens_cur += advance; return TRUE; }
static boolean parse_declaration( struct translate_ctx *ctx ) { struct tgsi_full_declaration decl; uint file; struct parsed_dcl_bracket brackets[2]; int num_brackets; uint writemask; 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); if (!eat_white( &ctx->cur )) { report_error( ctx, "Syntax error" ); return FALSE; } if (!parse_register_dcl( ctx, &file, brackets, &num_brackets)) return FALSE; if (!parse_opt_writemask( ctx, &writemask )) return FALSE; decl = tgsi_default_full_declaration(); decl.Declaration.File = file; decl.Declaration.UsageMask = writemask; if (num_brackets == 1) { decl.Range.First = brackets[0].first; decl.Range.Last = brackets[0].last; } else { decl.Range.First = brackets[1].first; decl.Range.Last = brackets[1].last; decl.Declaration.Dimension = 1; decl.Dim.Index2D = brackets[0].first; } 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 ); if (*cur == ',' && !is_vs_input) { uint i, j; cur++; eat_opt_white( &cur ); if (file == TGSI_FILE_RESOURCE) { for (i = 0; i < TGSI_TEXTURE_COUNT; i++) { if (str_match_no_case(&cur, texture_names[i])) { if (!is_digit_alpha_underscore(cur)) { decl.Resource.Resource = i; break; } } } if (i == TGSI_TEXTURE_COUNT) { report_error(ctx, "Expected texture target"); return FALSE; } eat_opt_white( &cur ); if (*cur != ',') { report_error( ctx, "Expected `,'" ); return FALSE; } ++cur; eat_opt_white( &cur ); for (j = 0; j < 4; ++j) { for (i = 0; i < PIPE_TYPE_COUNT; ++i) { if (str_match_no_case(&cur, type_names[i])) { if (!is_digit_alpha_underscore(cur)) { switch (j) { case 0: decl.Resource.ReturnTypeX = i; break; case 1: decl.Resource.ReturnTypeY = i; break; case 2: decl.Resource.ReturnTypeZ = i; break; case 3: decl.Resource.ReturnTypeW = i; break; default: assert(0); } break; } } } if (i == PIPE_TYPE_COUNT) { if (j == 0 || j > 2) { report_error(ctx, "Expected type name"); return FALSE; } break; } else { const char *cur2 = cur; eat_opt_white( &cur2 ); if (*cur2 == ',') { cur2++; eat_opt_white( &cur2 ); cur = cur2; continue; } else break; } } if (j < 4) { decl.Resource.ReturnTypeY = decl.Resource.ReturnTypeZ = decl.Resource.ReturnTypeW = decl.Resource.ReturnTypeX; } ctx->cur = cur; } else { for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) { if (str_match_no_case( &cur, semantic_names[i] )) { const char *cur2 = cur; uint index; if (is_digit_alpha_underscore( cur )) continue; eat_opt_white( &cur2 ); if (*cur2 == '[') { cur2++; eat_opt_white( &cur2 ); if (!parse_uint( &cur2, &index )) { report_error( ctx, "Expected literal integer" ); return FALSE; } eat_opt_white( &cur2 ); if (*cur2 != ']') { report_error( ctx, "Expected `]'" ); return FALSE; } cur2++; decl.Semantic.Index = index; cur = cur2; } decl.Declaration.Semantic = 1; decl.Semantic.Name = i; ctx->cur = cur; 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; eat_opt_white( &cur ); if (*cur == ',' && !is_vs_input) { uint i; cur++; eat_opt_white( &cur ); for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) { if (str_match_no_case( &cur, interpolate_names[i] )) { if (is_digit_alpha_underscore( cur )) continue; decl.Declaration.Interpolate = i; ctx->cur = cur; break; } } if (i == TGSI_INTERPOLATE_COUNT) { report_error( ctx, "Expected semantic or interpolate attribute" ); return FALSE; } } advance = tgsi_build_full_declaration( &decl, 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; return TRUE; }