|
|
/**
|
|
|
* MojoShader; generate shader programs from bytecode of compiled
|
|
|
* Direct3D shaders.
|
|
|
*
|
|
|
* Please see the file LICENSE.txt in the source's root directory.
|
|
|
*
|
|
|
* This file written by Ryan C. Gordon.
|
|
|
*/
|
|
|
|
|
|
#define __MOJOSHADER_INTERNAL__ 1
|
|
|
#include "mojoshader_profile.h"
|
|
|
|
|
|
#pragma GCC visibility push(hidden)
|
|
|
|
|
|
#if SUPPORT_PROFILE_D3D
|
|
|
|
|
|
const char *make_D3D_srcarg_string_in_buf(Context *ctx,
|
|
|
const SourceArgInfo *arg,
|
|
|
char *buf, size_t buflen)
|
|
|
{
|
|
|
const char *premod_str = "";
|
|
|
const char *postmod_str = "";
|
|
|
switch (arg->src_mod)
|
|
|
{
|
|
|
case SRCMOD_NEGATE:
|
|
|
premod_str = "-";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_BIASNEGATE:
|
|
|
premod_str = "-";
|
|
|
// fall through.
|
|
|
case SRCMOD_BIAS:
|
|
|
postmod_str = "_bias";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_SIGNNEGATE:
|
|
|
premod_str = "-";
|
|
|
// fall through.
|
|
|
case SRCMOD_SIGN:
|
|
|
postmod_str = "_bx2";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_COMPLEMENT:
|
|
|
premod_str = "1-";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_X2NEGATE:
|
|
|
premod_str = "-";
|
|
|
// fall through.
|
|
|
case SRCMOD_X2:
|
|
|
postmod_str = "_x2";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_DZ:
|
|
|
postmod_str = "_dz";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_DW:
|
|
|
postmod_str = "_dw";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_ABSNEGATE:
|
|
|
premod_str = "-";
|
|
|
// fall through.
|
|
|
case SRCMOD_ABS:
|
|
|
postmod_str = "_abs";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_NOT:
|
|
|
premod_str = "!";
|
|
|
break;
|
|
|
|
|
|
case SRCMOD_NONE:
|
|
|
case SRCMOD_TOTAL:
|
|
|
break; // stop compiler whining.
|
|
|
} // switch
|
|
|
|
|
|
|
|
|
char regnum_str[16];
|
|
|
const char *regtype_str = get_D3D_register_string(ctx, arg->regtype,
|
|
|
arg->regnum, regnum_str,
|
|
|
sizeof (regnum_str));
|
|
|
|
|
|
if (regtype_str == NULL)
|
|
|
{
|
|
|
fail(ctx, "Unknown source register type.");
|
|
|
*buf = '\0';
|
|
|
return buf;
|
|
|
} // if
|
|
|
|
|
|
const char *rel_lbracket = "";
|
|
|
const char *rel_rbracket = "";
|
|
|
char rel_swizzle[4] = { '\0' };
|
|
|
char rel_regnum_str[16] = { '\0' };
|
|
|
const char *rel_regtype_str = "";
|
|
|
if (arg->relative)
|
|
|
{
|
|
|
if (arg->relative_regtype == REG_TYPE_LOOP)
|
|
|
{
|
|
|
rel_swizzle[0] = '\0';
|
|
|
rel_swizzle[1] = '\0';
|
|
|
rel_swizzle[2] = '\0';
|
|
|
} // if
|
|
|
else
|
|
|
{
|
|
|
rel_swizzle[0] = '.';
|
|
|
rel_swizzle[1] = swizzle_channels[arg->relative_component];
|
|
|
rel_swizzle[2] = '\0';
|
|
|
} // else
|
|
|
|
|
|
rel_lbracket = "[";
|
|
|
rel_rbracket = "]";
|
|
|
rel_regtype_str = get_D3D_register_string(ctx, arg->relative_regtype,
|
|
|
arg->relative_regnum,
|
|
|
rel_regnum_str,
|
|
|
sizeof (rel_regnum_str));
|
|
|
|
|
|
if (regtype_str == NULL)
|
|
|
{
|
|
|
fail(ctx, "Unknown relative source register type.");
|
|
|
*buf = '\0';
|
|
|
return buf;
|
|
|
} // if
|
|
|
} // if
|
|
|
|
|
|
char swizzle_str[6];
|
|
|
size_t i = 0;
|
|
|
const int scalar = isscalar(ctx, ctx->shader_type, arg->regtype, arg->regnum);
|
|
|
if (!scalar && !no_swizzle(arg->swizzle))
|
|
|
{
|
|
|
swizzle_str[i++] = '.';
|
|
|
swizzle_str[i++] = swizzle_channels[arg->swizzle_x];
|
|
|
swizzle_str[i++] = swizzle_channels[arg->swizzle_y];
|
|
|
swizzle_str[i++] = swizzle_channels[arg->swizzle_z];
|
|
|
swizzle_str[i++] = swizzle_channels[arg->swizzle_w];
|
|
|
|
|
|
// .xyzz is the same as .xyz, .z is the same as .zzzz, etc.
|
|
|
while (swizzle_str[i-1] == swizzle_str[i-2])
|
|
|
i--;
|
|
|
} // if
|
|
|
swizzle_str[i] = '\0';
|
|
|
assert(i < sizeof (swizzle_str));
|
|
|
|
|
|
// !!! FIXME: c12[a0.x] actually needs to be c[a0.x + 12]
|
|
|
snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s",
|
|
|
premod_str, regtype_str, regnum_str, postmod_str,
|
|
|
rel_lbracket, rel_regtype_str, rel_regnum_str, rel_swizzle,
|
|
|
rel_rbracket, swizzle_str);
|
|
|
// !!! FIXME: make sure the scratch buffer was large enough.
|
|
|
return buf;
|
|
|
} // make_D3D_srcarg_string_in_buf
|
|
|
|
|
|
|
|
|
const char *make_D3D_destarg_string(Context *ctx, char *buf,
|
|
|
const size_t buflen)
|
|
|
{
|
|
|
const DestArgInfo *arg = &ctx->dest_arg;
|
|
|
|
|
|
const char *result_shift_str = "";
|
|
|
switch (arg->result_shift)
|
|
|
{
|
|
|
case 0x1: result_shift_str = "_x2"; break;
|
|
|
case 0x2: result_shift_str = "_x4"; break;
|
|
|
case 0x3: result_shift_str = "_x8"; break;
|
|
|
case 0xD: result_shift_str = "_d8"; break;
|
|
|
case 0xE: result_shift_str = "_d4"; break;
|
|
|
case 0xF: result_shift_str = "_d2"; break;
|
|
|
} // switch
|
|
|
|
|
|
const char *sat_str = (arg->result_mod & MOD_SATURATE) ? "_sat" : "";
|
|
|
const char *pp_str = (arg->result_mod & MOD_PP) ? "_pp" : "";
|
|
|
const char *cent_str = (arg->result_mod & MOD_CENTROID) ? "_centroid" : "";
|
|
|
|
|
|
char regnum_str[16];
|
|
|
const char *regtype_str = get_D3D_register_string(ctx, arg->regtype,
|
|
|
arg->regnum, regnum_str,
|
|
|
sizeof (regnum_str));
|
|
|
if (regtype_str == NULL)
|
|
|
{
|
|
|
fail(ctx, "Unknown destination register type.");
|
|
|
*buf = '\0';
|
|
|
return buf;
|
|
|
} // if
|
|
|
|
|
|
char writemask_str[6];
|
|
|
size_t i = 0;
|
|
|
const int scalar = isscalar(ctx, ctx->shader_type, arg->regtype, arg->regnum);
|
|
|
if (!scalar && !writemask_xyzw(arg->writemask))
|
|
|
{
|
|
|
writemask_str[i++] = '.';
|
|
|
if (arg->writemask0) writemask_str[i++] = 'x';
|
|
|
if (arg->writemask1) writemask_str[i++] = 'y';
|
|
|
if (arg->writemask2) writemask_str[i++] = 'z';
|
|
|
if (arg->writemask3) writemask_str[i++] = 'w';
|
|
|
} // if
|
|
|
writemask_str[i] = '\0';
|
|
|
assert(i < sizeof (writemask_str));
|
|
|
|
|
|
const char *pred_left = "";
|
|
|
const char *pred_right = "";
|
|
|
char pred[32] = { '\0' };
|
|
|
if (ctx->predicated)
|
|
|
{
|
|
|
pred_left = "(";
|
|
|
pred_right = ") ";
|
|
|
make_D3D_srcarg_string_in_buf(ctx, &ctx->predicate_arg,
|
|
|
pred, sizeof (pred));
|
|
|
} // if
|
|
|
|
|
|
// may turn out something like "_x2_sat_pp_centroid (!p0.x) r0.xyzw" ...
|
|
|
snprintf(buf, buflen, "%s%s%s%s %s%s%s%s%s%s",
|
|
|
result_shift_str, sat_str, pp_str, cent_str,
|
|
|
pred_left, pred, pred_right,
|
|
|
regtype_str, regnum_str, writemask_str);
|
|
|
// !!! FIXME: make sure the scratch buffer was large enough.
|
|
|
return buf;
|
|
|
} // make_D3D_destarg_string
|
|
|
|
|
|
|
|
|
const char *make_D3D_srcarg_string(Context *ctx, const size_t idx,
|
|
|
char *buf, size_t buflen)
|
|
|
{
|
|
|
if (idx >= STATICARRAYLEN(ctx->source_args))
|
|
|
{
|
|
|
fail(ctx, "Too many source args");
|
|
|
*buf = '\0';
|
|
|
return buf;
|
|
|
} // if
|
|
|
|
|
|
const SourceArgInfo *arg = &ctx->source_args[idx];
|
|
|
return make_D3D_srcarg_string_in_buf(ctx, arg, buf, buflen);
|
|
|
} // make_D3D_srcarg_string
|
|
|
|
|
|
const char *get_D3D_const_array_varname(Context *ctx, int base, int size)
|
|
|
{
|
|
|
char buf[64];
|
|
|
snprintf(buf, sizeof (buf), "c_array_%d_%d", base, size);
|
|
|
return StrDup(ctx, buf);
|
|
|
} // get_D3D_const_array_varname
|
|
|
|
|
|
|
|
|
void emit_D3D_start(Context *ctx, const char *profilestr)
|
|
|
{
|
|
|
const uint major = (uint) ctx->major_ver;
|
|
|
const uint minor = (uint) ctx->minor_ver;
|
|
|
char minor_str[16];
|
|
|
|
|
|
ctx->ignores_ctab = 1;
|
|
|
|
|
|
if (minor == 0xFF)
|
|
|
strcpy(minor_str, "sw");
|
|
|
else if ((major > 1) && (minor == 1))
|
|
|
strcpy(minor_str, "x"); // for >= SM2, apparently this is "x". Weird.
|
|
|
else
|
|
|
snprintf(minor_str, sizeof (minor_str), "%u", (uint) minor);
|
|
|
|
|
|
output_line(ctx, "%s_%u_%s", ctx->shader_type_str, major, minor_str);
|
|
|
} // emit_D3D_start
|
|
|
|
|
|
|
|
|
void emit_D3D_end(Context *ctx)
|
|
|
{
|
|
|
output_line(ctx, "end");
|
|
|
} // emit_D3D_end
|
|
|
|
|
|
|
|
|
void emit_D3D_phase(Context *ctx)
|
|
|
{
|
|
|
output_line(ctx, "phase");
|
|
|
} // emit_D3D_phase
|
|
|
|
|
|
|
|
|
void emit_D3D_finalize(Context *ctx)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_finalize
|
|
|
|
|
|
|
|
|
void emit_D3D_global(Context *ctx, RegisterType regtype, int regnum)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_global
|
|
|
|
|
|
|
|
|
void emit_D3D_array(Context *ctx, VariableList *var)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_array
|
|
|
|
|
|
|
|
|
void emit_D3D_const_array(Context *ctx, const ConstantsList *clist,
|
|
|
int base, int size)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_const_array
|
|
|
|
|
|
|
|
|
void emit_D3D_uniform(Context *ctx, RegisterType regtype, int regnum,
|
|
|
const VariableList *var)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_uniform
|
|
|
|
|
|
|
|
|
void emit_D3D_sampler(Context *ctx, int s, TextureType ttype, int tb)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_sampler
|
|
|
|
|
|
|
|
|
void emit_D3D_attribute(Context *ctx, RegisterType regtype, int regnum,
|
|
|
MOJOSHADER_usage usage, int index, int wmask,
|
|
|
int flags)
|
|
|
{
|
|
|
// no-op.
|
|
|
} // emit_D3D_attribute
|
|
|
|
|
|
|
|
|
void emit_D3D_RESERVED(Context *ctx)
|
|
|
{
|
|
|
// do nothing; fails in the state machine.
|
|
|
} // emit_D3D_RESERVED
|
|
|
|
|
|
|
|
|
// Generic D3D opcode emitters. A list of macros generate all the entry points
|
|
|
// that call into these...
|
|
|
|
|
|
char *lowercase(char *dst, const char *src)
|
|
|
{
|
|
|
int i = 0;
|
|
|
do
|
|
|
{
|
|
|
const char ch = src[i];
|
|
|
dst[i] = (((ch >= 'A') && (ch <= 'Z')) ? (ch - ('A' - 'a')) : ch);
|
|
|
} while (src[i++]);
|
|
|
return dst;
|
|
|
} // lowercase
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_d(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char dst[64]; make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s%s", ctx->coissue ? "+" : "", opcode, dst);
|
|
|
} // emit_D3D_opcode_d
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_s(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char src0[64]; make_D3D_srcarg_string(ctx, 0, src0, sizeof (src0));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s %s", ctx->coissue ? "+" : "", opcode, src0);
|
|
|
} // emit_D3D_opcode_s
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_ss(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char src0[64]; make_D3D_srcarg_string(ctx, 0, src0, sizeof (src0));
|
|
|
char src1[64]; make_D3D_srcarg_string(ctx, 1, src1, sizeof (src1));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s %s, %s", ctx->coissue ? "+" : "", opcode, src0, src1);
|
|
|
} // emit_D3D_opcode_ss
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_ds(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char dst[64]; make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
char src0[64]; make_D3D_srcarg_string(ctx, 0, src0, sizeof (src0));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s%s, %s", ctx->coissue ? "+" : "", opcode, dst, src0);
|
|
|
} // emit_D3D_opcode_ds
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_dss(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char dst[64]; make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
char src0[64]; make_D3D_srcarg_string(ctx, 0, src0, sizeof (src0));
|
|
|
char src1[64]; make_D3D_srcarg_string(ctx, 1, src1, sizeof (src1));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s%s, %s, %s", ctx->coissue ? "+" : "",
|
|
|
opcode, dst, src0, src1);
|
|
|
} // emit_D3D_opcode_dss
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_dsss(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char dst[64]; make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
char src0[64]; make_D3D_srcarg_string(ctx, 0, src0, sizeof (src0));
|
|
|
char src1[64]; make_D3D_srcarg_string(ctx, 1, src1, sizeof (src1));
|
|
|
char src2[64]; make_D3D_srcarg_string(ctx, 2, src2, sizeof (src2));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s%s, %s, %s, %s", ctx->coissue ? "+" : "",
|
|
|
opcode, dst, src0, src1, src2);
|
|
|
} // emit_D3D_opcode_dsss
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode_dssss(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
char dst[64]; make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
char src0[64]; make_D3D_srcarg_string(ctx, 0, src0, sizeof (src0));
|
|
|
char src1[64]; make_D3D_srcarg_string(ctx, 1, src1, sizeof (src1));
|
|
|
char src2[64]; make_D3D_srcarg_string(ctx, 2, src2, sizeof (src2));
|
|
|
char src3[64]; make_D3D_srcarg_string(ctx, 3, src3, sizeof (src3));
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx,"%s%s%s, %s, %s, %s, %s", ctx->coissue ? "+" : "",
|
|
|
opcode, dst, src0, src1, src2, src3);
|
|
|
} // emit_D3D_opcode_dssss
|
|
|
|
|
|
|
|
|
void emit_D3D_opcode(Context *ctx, const char *opcode)
|
|
|
{
|
|
|
opcode = lowercase((char *) alloca(strlen(opcode) + 1), opcode);
|
|
|
output_line(ctx, "%s%s", ctx->coissue ? "+" : "", opcode);
|
|
|
} // emit_D3D_opcode
|
|
|
|
|
|
|
|
|
#define EMIT_D3D_OPCODE_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_D_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_d(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_S_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_s(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_SS_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_ss(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_DS_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_ds(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_DSS_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_dss(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_DSSS_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_dsss(ctx, #op); \
|
|
|
}
|
|
|
#define EMIT_D3D_OPCODE_DSSSS_FUNC(op) \
|
|
|
void emit_D3D_##op(Context *ctx) { \
|
|
|
emit_D3D_opcode_dssss(ctx, #op); \
|
|
|
}
|
|
|
|
|
|
EMIT_D3D_OPCODE_FUNC(NOP)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(MOV)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(ADD)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(SUB)
|
|
|
EMIT_D3D_OPCODE_DSSS_FUNC(MAD)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(MUL)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(RCP)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(RSQ)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(DP3)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(DP4)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(MIN)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(MAX)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(SLT)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(SGE)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(EXP)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(LOG)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(LIT)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(DST)
|
|
|
EMIT_D3D_OPCODE_DSSS_FUNC(LRP)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(FRC)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(M4X4)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(M4X3)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(M3X4)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(M3X3)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(M3X2)
|
|
|
EMIT_D3D_OPCODE_S_FUNC(CALL)
|
|
|
EMIT_D3D_OPCODE_SS_FUNC(CALLNZ)
|
|
|
EMIT_D3D_OPCODE_SS_FUNC(LOOP)
|
|
|
EMIT_D3D_OPCODE_FUNC(RET)
|
|
|
EMIT_D3D_OPCODE_FUNC(ENDLOOP)
|
|
|
EMIT_D3D_OPCODE_S_FUNC(LABEL)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(POW)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(CRS)
|
|
|
EMIT_D3D_OPCODE_DSSS_FUNC(SGN)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(ABS)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(NRM)
|
|
|
EMIT_D3D_OPCODE_S_FUNC(REP)
|
|
|
EMIT_D3D_OPCODE_FUNC(ENDREP)
|
|
|
EMIT_D3D_OPCODE_S_FUNC(IF)
|
|
|
EMIT_D3D_OPCODE_FUNC(ELSE)
|
|
|
EMIT_D3D_OPCODE_FUNC(ENDIF)
|
|
|
EMIT_D3D_OPCODE_FUNC(BREAK)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(MOVA)
|
|
|
EMIT_D3D_OPCODE_D_FUNC(TEXKILL)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXBEM)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXBEML)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXREG2AR)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXREG2GB)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X2PAD)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X2TEX)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3PAD)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3TEX)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(TEXM3X3SPEC)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3VSPEC)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(EXPP)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(LOGP)
|
|
|
EMIT_D3D_OPCODE_DSSS_FUNC(CND)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXREG2RGB)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXDP3TEX)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X2DEPTH)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXDP3)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(TEXM3X3)
|
|
|
EMIT_D3D_OPCODE_D_FUNC(TEXDEPTH)
|
|
|
EMIT_D3D_OPCODE_DSSS_FUNC(CMP)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(BEM)
|
|
|
EMIT_D3D_OPCODE_DSSS_FUNC(DP2ADD)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(DSX)
|
|
|
EMIT_D3D_OPCODE_DS_FUNC(DSY)
|
|
|
EMIT_D3D_OPCODE_DSSSS_FUNC(TEXLDD)
|
|
|
EMIT_D3D_OPCODE_DSS_FUNC(TEXLDL)
|
|
|
EMIT_D3D_OPCODE_S_FUNC(BREAKP)
|
|
|
|
|
|
// special cases for comparison opcodes...
|
|
|
const char *get_D3D_comparison_string(Context *ctx)
|
|
|
{
|
|
|
const char *comps[] = {
|
|
|
"", "_gt", "_eq", "_ge", "_lt", "_ne", "_le"
|
|
|
};
|
|
|
|
|
|
if (ctx->instruction_controls >= STATICARRAYLEN(comps))
|
|
|
{
|
|
|
fail(ctx, "unknown comparison control");
|
|
|
return "";
|
|
|
} // if
|
|
|
|
|
|
return comps[ctx->instruction_controls];
|
|
|
} // get_D3D_comparison_string
|
|
|
|
|
|
void emit_D3D_BREAKC(Context *ctx)
|
|
|
{
|
|
|
char op[16];
|
|
|
snprintf(op, sizeof (op), "break%s", get_D3D_comparison_string(ctx));
|
|
|
emit_D3D_opcode_ss(ctx, op);
|
|
|
} // emit_D3D_BREAKC
|
|
|
|
|
|
void emit_D3D_IFC(Context *ctx)
|
|
|
{
|
|
|
char op[16];
|
|
|
snprintf(op, sizeof (op), "if%s", get_D3D_comparison_string(ctx));
|
|
|
emit_D3D_opcode_ss(ctx, op);
|
|
|
} // emit_D3D_IFC
|
|
|
|
|
|
void emit_D3D_SETP(Context *ctx)
|
|
|
{
|
|
|
char op[16];
|
|
|
snprintf(op, sizeof (op), "setp%s", get_D3D_comparison_string(ctx));
|
|
|
emit_D3D_opcode_dss(ctx, op);
|
|
|
} // emit_D3D_SETP
|
|
|
|
|
|
void emit_D3D_DEF(Context *ctx)
|
|
|
{
|
|
|
char dst[64];
|
|
|
make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
const float *val = (const float *) ctx->dwords; // !!! FIXME: could be int?
|
|
|
char val0[32];
|
|
|
char val1[32];
|
|
|
char val2[32];
|
|
|
char val3[32];
|
|
|
floatstr(ctx, val0, sizeof (val0), val[0], 0);
|
|
|
floatstr(ctx, val1, sizeof (val1), val[1], 0);
|
|
|
floatstr(ctx, val2, sizeof (val2), val[2], 0);
|
|
|
floatstr(ctx, val3, sizeof (val3), val[3], 0);
|
|
|
output_line(ctx, "def%s, %s, %s, %s, %s", dst, val0, val1, val2, val3);
|
|
|
} // emit_D3D_DEF
|
|
|
|
|
|
void emit_D3D_DEFI(Context *ctx)
|
|
|
{
|
|
|
char dst[64];
|
|
|
make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
const int32 *x = (const int32 *) ctx->dwords;
|
|
|
output_line(ctx, "defi%s, %d, %d, %d, %d", dst,
|
|
|
(int) x[0], (int) x[1], (int) x[2], (int) x[3]);
|
|
|
} // emit_D3D_DEFI
|
|
|
|
|
|
void emit_D3D_DEFB(Context *ctx)
|
|
|
{
|
|
|
char dst[64];
|
|
|
make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
output_line(ctx, "defb%s, %s", dst, ctx->dwords[0] ? "true" : "false");
|
|
|
} // emit_D3D_DEFB
|
|
|
|
|
|
|
|
|
static const char *usagestrs[] = {
|
|
|
"_position", "_blendweight", "_blendindices", "_normal", "_psize",
|
|
|
"_texcoord", "_tangent", "_binormal", "_tessfactor", "_positiont",
|
|
|
"_color", "_fog", "_depth", "_sample"
|
|
|
};
|
|
|
|
|
|
void emit_D3D_DCL(Context *ctx)
|
|
|
{
|
|
|
char dst[64];
|
|
|
make_D3D_destarg_string(ctx, dst, sizeof (dst));
|
|
|
const DestArgInfo *arg = &ctx->dest_arg;
|
|
|
const char *usage_str = "";
|
|
|
char index_str[16] = { '\0' };
|
|
|
|
|
|
if (arg->regtype == REG_TYPE_SAMPLER)
|
|
|
{
|
|
|
switch ((const TextureType) ctx->dwords[0])
|
|
|
{
|
|
|
case TEXTURE_TYPE_2D: usage_str = "_2d"; break;
|
|
|
case TEXTURE_TYPE_CUBE: usage_str = "_cube"; break;
|
|
|
case TEXTURE_TYPE_VOLUME: usage_str = "_volume"; break;
|
|
|
default: fail(ctx, "unknown sampler texture type"); return;
|
|
|
} // switch
|
|
|
} // if
|
|
|
|
|
|
else if (arg->regtype == REG_TYPE_MISCTYPE)
|
|
|
{
|
|
|
switch ((const MiscTypeType) arg->regnum)
|
|
|
{
|
|
|
case MISCTYPE_TYPE_POSITION:
|
|
|
case MISCTYPE_TYPE_FACE:
|
|
|
usage_str = ""; // just become "dcl vFace" or whatever.
|
|
|
break;
|
|
|
default: fail(ctx, "unknown misc register type"); return;
|
|
|
} // switch
|
|
|
} // else if
|
|
|
|
|
|
else
|
|
|
{
|
|
|
const uint32 usage = ctx->dwords[0];
|
|
|
const uint32 index = ctx->dwords[1];
|
|
|
usage_str = usagestrs[usage];
|
|
|
if (index != 0)
|
|
|
snprintf(index_str, sizeof (index_str), "%u", (uint) index);
|
|
|
} // else
|
|
|
|
|
|
output_line(ctx, "dcl%s%s%s", usage_str, index_str, dst);
|
|
|
} // emit_D3D_DCL
|
|
|
|
|
|
|
|
|
void emit_D3D_TEXCRD(Context *ctx)
|
|
|
{
|
|
|
// this opcode looks and acts differently depending on the shader model.
|
|
|
if (shader_version_atleast(ctx, 1, 4))
|
|
|
emit_D3D_opcode_ds(ctx, "texcrd");
|
|
|
else
|
|
|
emit_D3D_opcode_d(ctx, "texcoord");
|
|
|
} // emit_D3D_TEXCOORD
|
|
|
|
|
|
void emit_D3D_TEXLD(Context *ctx)
|
|
|
{
|
|
|
// this opcode looks and acts differently depending on the shader model.
|
|
|
if (shader_version_atleast(ctx, 2, 0))
|
|
|
{
|
|
|
if (ctx->instruction_controls == CONTROL_TEXLD)
|
|
|
emit_D3D_opcode_dss(ctx, "texld");
|
|
|
else if (ctx->instruction_controls == CONTROL_TEXLDP)
|
|
|
emit_D3D_opcode_dss(ctx, "texldp");
|
|
|
else if (ctx->instruction_controls == CONTROL_TEXLDB)
|
|
|
emit_D3D_opcode_dss(ctx, "texldb");
|
|
|
} // if
|
|
|
|
|
|
else if (shader_version_atleast(ctx, 1, 4))
|
|
|
{
|
|
|
emit_D3D_opcode_ds(ctx, "texld");
|
|
|
} // else if
|
|
|
|
|
|
else
|
|
|
{
|
|
|
emit_D3D_opcode_d(ctx, "tex");
|
|
|
} // else
|
|
|
} // emit_D3D_TEXLD
|
|
|
|
|
|
void emit_D3D_SINCOS(Context *ctx)
|
|
|
{
|
|
|
// this opcode needs extra registers for sm2 and lower.
|
|
|
if (!shader_version_atleast(ctx, 3, 0))
|
|
|
emit_D3D_opcode_dsss(ctx, "sincos");
|
|
|
else
|
|
|
emit_D3D_opcode_ds(ctx, "sincos");
|
|
|
} // emit_D3D_SINCOS
|
|
|
|
|
|
#endif // SUPPORT_PROFILE_D3D
|
|
|
|
|
|
#pragma GCC visibility pop
|
|
|
|