mojoshader.c
branchtrunk
changeset 152 cc7c38dfe145
parent 151 1667680fe402
child 154 ebd0921fdd39
equal deleted inserted replaced
151:1667680fe402 152:cc7c38dfe145
   263 
   263 
   264 typedef struct
   264 typedef struct
   265 {
   265 {
   266     const uint32 *token;   // this is the unmolested token in the stream.
   266     const uint32 *token;   // this is the unmolested token in the stream.
   267     int regnum;
   267     int regnum;
   268     int relative;
       
   269     int swizzle;  // xyzw (all four, not split out).
   268     int swizzle;  // xyzw (all four, not split out).
   270     int swizzle_x;
   269     int swizzle_x;
   271     int swizzle_y;
   270     int swizzle_y;
   272     int swizzle_z;
   271     int swizzle_z;
   273     int swizzle_w;
   272     int swizzle_w;
   274     SourceMod src_mod;
   273     SourceMod src_mod;
   275     RegisterType regtype;
   274     RegisterType regtype;
       
   275     int relative;
       
   276     RegisterType relative_regtype;
       
   277     int relative_regnum;
       
   278     int relative_component;
   276 } SourceArgInfo;
   279 } SourceArgInfo;
   277 
   280 
   278 
   281 
   279 typedef enum
   282 typedef enum
   280 {
   283 {
   927     {
   930     {
   928         fail(ctx, "Unknown source register type.");
   931         fail(ctx, "Unknown source register type.");
   929         return "";
   932         return "";
   930     } // if
   933     } // if
   931 
   934 
       
   935     const char *rel_lbracket = "";
       
   936     const char *rel_rbracket = "";
       
   937     char rel_swizzle[4] = { '\0' };
       
   938     char rel_regnum_str[16] = { '\0' };
       
   939     const char *rel_regtype_str = "";
       
   940     if (arg->relative)
       
   941     {
       
   942         rel_swizzle[0] = '.';
       
   943         rel_swizzle[1] = swizzle_channels[arg->relative_component];
       
   944         rel_swizzle[2] = '\0';
       
   945         rel_lbracket = "[";
       
   946         rel_rbracket = "]";
       
   947         rel_regtype_str = get_D3D_register_string(ctx, arg->relative_regtype,
       
   948                                                   arg->relative_regnum,
       
   949                                                   rel_regnum_str,
       
   950                                                   sizeof (rel_regnum_str));
       
   951 
       
   952         if (regtype_str == NULL)
       
   953         {
       
   954             fail(ctx, "Unknown relative source register type.");
       
   955             return "";
       
   956         } // if
       
   957     } // if
       
   958 
   932     char swizzle_str[6];
   959     char swizzle_str[6];
   933     int i = 0;
   960     int i = 0;
   934     if (arg->swizzle != 0xE4)  // 0xE4 == 11100100 ... 3 2 1 0. No swizzle.
   961     if (arg->swizzle != 0xE4)  // 0xE4 == 11100100 ... 3 2 1 0. No swizzle.
   935     {
   962     {
   936         swizzle_str[i++] = '.';
   963         swizzle_str[i++] = '.';
   944             i--;
   971             i--;
   945     } // if
   972     } // if
   946     swizzle_str[i] = '\0';
   973     swizzle_str[i] = '\0';
   947     assert(i < sizeof (swizzle_str));
   974     assert(i < sizeof (swizzle_str));
   948 
   975 
   949     snprintf(buf, buflen, "%s%s%s%s%s",
   976     snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s",
   950              premod_str, regtype_str, regnum_str, postmod_str, swizzle_str);
   977              premod_str, regtype_str, regnum_str, postmod_str,
       
   978              rel_lbracket, rel_regtype_str, rel_regnum_str, rel_swizzle,
       
   979              rel_rbracket, swizzle_str);
   951     // !!! FIXME: make sure the scratch buffer was large enough.
   980     // !!! FIXME: make sure the scratch buffer was large enough.
   952     return buf;
   981     return buf;
   953 } // make_D3D_sourcearg_string_in_buf
   982 } // make_D3D_sourcearg_string_in_buf
   954 
   983 
   955 
   984 
  2941     {
  2970     {
  2942         if (!shader_is_vertex(ctx))
  2971         if (!shader_is_vertex(ctx))
  2943             return fail(ctx, "Relative addressing in non-vertex shader");
  2972             return fail(ctx, "Relative addressing in non-vertex shader");
  2944         else if (!shader_version_atleast(ctx, 3, 0))
  2973         else if (!shader_version_atleast(ctx, 3, 0))
  2945             return fail(ctx, "Relative addressing in vertex shader version < 3.0");
  2974             return fail(ctx, "Relative addressing in vertex shader version < 3.0");
  2946         return fail(ctx, "Relative addressing is unsupported");  // !!! FIXME
  2975         // !!! FIXME: I don't have a shader that has a relative dest currently.
       
  2976         return fail(ctx, "Relative addressing of dest tokens is unsupported");
  2947     } // if
  2977     } // if
  2948 
  2978 
  2949     const int s = info->result_shift;
  2979     const int s = info->result_shift;
  2950     if (s != 0)
  2980     if (s != 0)
  2951     {
  2981     {
  2987 } // parse_destination_token
  3017 } // parse_destination_token
  2988 
  3018 
  2989 
  3019 
  2990 static int parse_source_token(Context *ctx, SourceArgInfo *info)
  3020 static int parse_source_token(Context *ctx, SourceArgInfo *info)
  2991 {
  3021 {
       
  3022     int retval = 1;
       
  3023 
  2992     if (isfail(ctx))
  3024     if (isfail(ctx))
  2993         return FAIL;  // already failed elsewhere.
  3025         return FAIL;  // already failed elsewhere.
  2994 
  3026 
  2995     if (ctx->tokencount == 0)
  3027     if (ctx->tokencount == 0)
  2996         return fail(ctx, "Out of tokens in source parameter");
  3028         return fail(ctx, "Out of tokens in source parameter");
  3021 
  3053 
  3022     if (info->relative)
  3054     if (info->relative)
  3023     {
  3055     {
  3024         if ( (shader_is_pixel(ctx)) && (!shader_version_atleast(ctx, 3, 0)) )
  3056         if ( (shader_is_pixel(ctx)) && (!shader_version_atleast(ctx, 3, 0)) )
  3025             return fail(ctx, "Relative addressing in pixel shader version < 3.0");
  3057             return fail(ctx, "Relative addressing in pixel shader version < 3.0");
  3026         return fail(ctx, "Relative addressing is unsupported");  // !!! FIXME
  3058 
       
  3059         if (ctx->tokencount == 0)
       
  3060             return fail(ctx, "Out of tokens in relative source parameter");
       
  3061 
       
  3062         const uint32 reltoken = SWAP32(*(ctx->tokens));
       
  3063         ctx->tokens++;  // swallow token for now, for multiple calls in a row.
       
  3064         ctx->tokencount--;  // swallow token for now, for multiple calls in a row.
       
  3065 
       
  3066         const int relswiz  = (int) ((reltoken >> 16) & 0xFF);
       
  3067         info->relative_component = relswiz & 0x3;
       
  3068         info->relative_regnum = (int) (reltoken & 0x7ff);
       
  3069         info->relative_regtype = (RegisterType)
       
  3070                                     (((reltoken >> 28) & 0x7) |
       
  3071                                     ((reltoken >> 8) & 0x18));
       
  3072 
       
  3073         if (((reltoken >> 31) & 0x1) == 0)
       
  3074             return fail(ctx, "bit #31 in relative address must be set");
       
  3075 
       
  3076         if ((reltoken & 0xF00E000) != 0)  // usused bits.
       
  3077             return fail(ctx, "relative address reserved bit must be zero");
       
  3078 
       
  3079         switch (info->relative_regtype)
       
  3080         {
       
  3081             case REG_TYPE_LOOP:
       
  3082             case REG_TYPE_ADDRESS:
       
  3083                 break;
       
  3084             default:
       
  3085                 return fail(ctx, "invalid register for relative address");
       
  3086                 break;
       
  3087         } // switch
       
  3088 
       
  3089         if (info->relative_regnum != 0)  // true for now.
       
  3090             return fail(ctx, "invalid register for relative address");
       
  3091 
       
  3092         switch (info->regtype)
       
  3093         {
       
  3094             case REG_TYPE_CONST:
       
  3095             case REG_TYPE_CONST2:
       
  3096             case REG_TYPE_CONST3:
       
  3097             case REG_TYPE_CONST4:
       
  3098                 break;
       
  3099             default:
       
  3100                 return fail(ctx, "relative addressing of non-const register");
       
  3101                 break;
       
  3102         } // switch
       
  3103 
       
  3104         if (!replicate_swizzle(relswiz))
       
  3105             return fail(ctx, "relative address needs replicate swizzle");
       
  3106 
       
  3107         set_used_register(ctx, info->relative_regtype, info->relative_regnum);
       
  3108         retval++;
  3027     } // if
  3109     } // if
  3028 
  3110 
  3029     if ( info->src_mod >= SRCMOD_TOTAL )
  3111     if ( info->src_mod >= SRCMOD_TOTAL )
  3030         return fail(ctx, "Unknown source modifier");
  3112         return fail(ctx, "Unknown source modifier");
  3031 
  3113 
  3032     set_used_register(ctx, info->regtype, info->regnum);
  3114     set_used_register(ctx, info->regtype, info->regnum);
  3033     return 1;
  3115     return retval;
  3034 } // parse_source_token
  3116 } // parse_source_token
  3035 
  3117 
  3036 
  3118 
  3037 static int parse_predicated_token(Context *ctx)
  3119 static int parse_predicated_token(Context *ctx)
  3038 {
  3120 {
  3046 
  3128 
  3047     // 0xE4 == 11100100 ... 3 2 1 0. No swizzle.
  3129     // 0xE4 == 11100100 ... 3 2 1 0. No swizzle.
  3048     if ( (arg->swizzle != 0xE4) && (!replicate_swizzle(arg->swizzle)) )
  3130     if ( (arg->swizzle != 0xE4) && (!replicate_swizzle(arg->swizzle)) )
  3049         return fail(ctx, "Predicated instruction register has wrong swizzle");
  3131         return fail(ctx, "Predicated instruction register has wrong swizzle");
  3050 
  3132 
  3051     return 0;
  3133     if (arg->relative)  // I'm pretty sure this is illegal...?
       
  3134         return fail(ctx, "relative addressing in predicated token");
       
  3135 
       
  3136     return 1;
  3052 } // parse_predicated_token
  3137 } // parse_predicated_token
  3053 
  3138 
  3054 
  3139 
  3055 static int parse_args_NULL(Context *ctx)
  3140 static int parse_args_NULL(Context *ctx)
  3056 {
  3141 {
  3060 
  3145 
  3061 static int parse_args_DEF(Context *ctx)
  3146 static int parse_args_DEF(Context *ctx)
  3062 {
  3147 {
  3063     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
  3148     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
  3064         return FAIL;
  3149         return FAIL;
       
  3150 
       
  3151     if (ctx->dest_args[0].relative)  // I'm pretty sure this is illegal...?
       
  3152         return fail(ctx, "relative addressing in DEFB");
  3065 
  3153 
  3066     ctx->dwords[0] = SWAP32(ctx->tokens[0]);
  3154     ctx->dwords[0] = SWAP32(ctx->tokens[0]);
  3067     ctx->dwords[1] = SWAP32(ctx->tokens[1]);
  3155     ctx->dwords[1] = SWAP32(ctx->tokens[1]);
  3068     ctx->dwords[2] = SWAP32(ctx->tokens[2]);
  3156     ctx->dwords[2] = SWAP32(ctx->tokens[2]);
  3069     ctx->dwords[3] = SWAP32(ctx->tokens[3]);
  3157     ctx->dwords[3] = SWAP32(ctx->tokens[3]);
  3075 static int parse_args_DEFB(Context *ctx)
  3163 static int parse_args_DEFB(Context *ctx)
  3076 {
  3164 {
  3077     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
  3165     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
  3078         return FAIL;
  3166         return FAIL;
  3079 
  3167 
       
  3168     if (ctx->dest_args[0].relative)  // I'm pretty sure this is illegal...?
       
  3169         return fail(ctx, "relative addressing in DEFB");
       
  3170 
  3080     ctx->dwords[0] = *(ctx->tokens) ? 1 : 0;
  3171     ctx->dwords[0] = *(ctx->tokens) ? 1 : 0;
  3081 
  3172 
  3082     return 3;
  3173     return 3;
  3083 } // parse_args_DEFB
  3174 } // parse_args_DEFB
  3084 
  3175 
  3095 
  3186 
  3096     ctx->tokens++;
  3187     ctx->tokens++;
  3097     ctx->tokencount--;
  3188     ctx->tokencount--;
  3098     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
  3189     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL)
  3099         return FAIL;
  3190         return FAIL;
       
  3191 
       
  3192     if (ctx->dest_args[0].relative)  // I'm pretty sure this is illegal...?
       
  3193         return fail(ctx, "relative addressing in DCL");
  3100 
  3194 
  3101     const RegisterType regtype = ctx->dest_args[0].regtype;
  3195     const RegisterType regtype = ctx->dest_args[0].regtype;
  3102     const int regnum = ctx->dest_args[0].regnum;
  3196     const int regnum = ctx->dest_args[0].regnum;
  3103     if ( (shader_is_pixel(ctx)) && (shader_version_atleast(ctx, 3, 0)) )
  3197     if ( (shader_is_pixel(ctx)) && (shader_version_atleast(ctx, 3, 0)) )
  3104     {
  3198     {
  3226 } // parse_args_DCL
  3320 } // parse_args_DCL
  3227 
  3321 
  3228 
  3322 
  3229 static int parse_args_D(Context *ctx)
  3323 static int parse_args_D(Context *ctx)
  3230 {
  3324 {
  3231     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
  3325     int retval = 1;
  3232     return 2;
  3326     retval += parse_destination_token(ctx, &ctx->dest_args[0]);
       
  3327     return isfail(ctx) ? FAIL : retval;
  3233 } // parse_args_D
  3328 } // parse_args_D
  3234 
  3329 
  3235 
  3330 
  3236 static int parse_args_S(Context *ctx)
  3331 static int parse_args_S(Context *ctx)
  3237 {
  3332 {
  3238     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
  3333     int retval = 1;
  3239     return 2;
  3334     retval += parse_source_token(ctx, &ctx->source_args[0]);
       
  3335     return isfail(ctx) ? FAIL : retval;
  3240 } // parse_args_S
  3336 } // parse_args_S
  3241 
  3337 
  3242 
  3338 
  3243 static int parse_args_SS(Context *ctx)
  3339 static int parse_args_SS(Context *ctx)
  3244 {
  3340 {
  3245     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
  3341     int retval = 1;
  3246     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
  3342     retval += parse_source_token(ctx, &ctx->source_args[0]);
  3247     return 3;
  3343     retval += parse_source_token(ctx, &ctx->source_args[1]);
       
  3344     return isfail(ctx) ? FAIL : retval;
  3248 } // parse_args_SS
  3345 } // parse_args_SS
  3249 
  3346 
  3250 
  3347 
  3251 static int parse_args_DS(Context *ctx)
  3348 static int parse_args_DS(Context *ctx)
  3252 {
  3349 {
  3253     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
  3350     int retval = 1;
  3254     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
  3351     retval += parse_destination_token(ctx, &ctx->dest_args[0]);
  3255     return 3;
  3352     retval += parse_source_token(ctx, &ctx->source_args[0]);
       
  3353     return isfail(ctx) ? FAIL : retval;
  3256 } // parse_args_DS
  3354 } // parse_args_DS
  3257 
  3355 
  3258 
  3356 
  3259 static int parse_args_DSS(Context *ctx)
  3357 static int parse_args_DSS(Context *ctx)
  3260 {
  3358 {
  3261     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
  3359     int retval = 1;
  3262     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
  3360     retval += parse_destination_token(ctx, &ctx->dest_args[0]);
  3263     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
  3361     retval += parse_source_token(ctx, &ctx->source_args[0]);
  3264     return 4;
  3362     retval += parse_source_token(ctx, &ctx->source_args[1]);
       
  3363     return isfail(ctx) ? FAIL : retval;
  3265 } // parse_args_DSS
  3364 } // parse_args_DSS
  3266 
  3365 
  3267 
  3366 
  3268 static int parse_args_DSSS(Context *ctx)
  3367 static int parse_args_DSSS(Context *ctx)
  3269 {
  3368 {
  3270     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
  3369     int retval = 1;
  3271     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
  3370     retval += parse_destination_token(ctx, &ctx->dest_args[0]);
  3272     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
  3371     retval += parse_source_token(ctx, &ctx->source_args[0]);
  3273     if (parse_source_token(ctx, &ctx->source_args[2]) == FAIL) return FAIL;
  3372     retval += parse_source_token(ctx, &ctx->source_args[1]);
  3274     return 5;
  3373     retval += parse_source_token(ctx, &ctx->source_args[2]);
       
  3374     return isfail(ctx) ? FAIL : retval;
  3275 } // parse_args_DSSS
  3375 } // parse_args_DSSS
  3276 
  3376 
  3277 
  3377 
  3278 static int parse_args_DSSSS(Context *ctx)
  3378 static int parse_args_DSSSS(Context *ctx)
  3279 {
  3379 {
  3280     if (parse_destination_token(ctx, &ctx->dest_args[0]) == FAIL) return FAIL;
  3380     int retval = 1;
  3281     if (parse_source_token(ctx, &ctx->source_args[0]) == FAIL) return FAIL;
  3381     retval += parse_destination_token(ctx, &ctx->dest_args[0]);
  3282     if (parse_source_token(ctx, &ctx->source_args[1]) == FAIL) return FAIL;
  3382     retval += parse_source_token(ctx, &ctx->source_args[0]);
  3283     if (parse_source_token(ctx, &ctx->source_args[2]) == FAIL) return FAIL;
  3383     retval += parse_source_token(ctx, &ctx->source_args[1]);
  3284     if (parse_source_token(ctx, &ctx->source_args[3]) == FAIL) return FAIL;
  3384     retval += parse_source_token(ctx, &ctx->source_args[2]);
  3285     return 6;
  3385     retval += parse_source_token(ctx, &ctx->source_args[3]);
       
  3386     return isfail(ctx) ? FAIL : retval;
  3286 } // parse_args_DSSSS
  3387 } // parse_args_DSSSS
  3287 
  3388 
  3288 
  3389 
  3289 static int parse_args_SINCOS(Context *ctx)
  3390 static int parse_args_SINCOS(Context *ctx)
  3290 {
  3391 {
  3900     ctx->tokencount--;
  4001     ctx->tokencount--;
  3901     retval = instruction->parse_args(ctx);
  4002     retval = instruction->parse_args(ctx);
  3902     assert((isfail(ctx)) || (retval >= 0));
  4003     assert((isfail(ctx)) || (retval >= 0));
  3903 
  4004 
  3904     if ( (!isfail(ctx)) && (predicated) )
  4005     if ( (!isfail(ctx)) && (predicated) )
  3905         parse_predicated_token(ctx);
  4006     {
       
  4007         if (parse_predicated_token(ctx) != FAIL)
       
  4008             retval++;  // one more token.
       
  4009     } // if
  3906 
  4010 
  3907     // parse_args() moves these forward for convenience...reset them.
  4011     // parse_args() moves these forward for convenience...reset them.
  3908     ctx->tokens = start_tokens;
  4012     ctx->tokens = start_tokens;
  3909     ctx->tokencount = start_tokencount;
  4013     ctx->tokencount = start_tokencount;
  3910 
  4014 
  3932         {
  4036         {
  3933             if (retval != (insttoks+1))
  4037             if (retval != (insttoks+1))
  3934             {
  4038             {
  3935                 return failf(ctx,
  4039                 return failf(ctx,
  3936                         "wrong token count (%u, not %u) for opcode '%s'.",
  4040                         "wrong token count (%u, not %u) for opcode '%s'.",
  3937                         (uint) insttoks, (uint) retval,
  4041                         (uint) retval, (uint) (insttoks+1),
  3938                         instruction->opcode_string);
  4042                         instruction->opcode_string);
  3939             } // if
  4043             } // if
  3940         } // else
  4044         } // else
  3941     } // if
  4045     } // if
  3942 
  4046