nv2a: Add custom mutable string object (QString is now immutable)

This commit is contained in:
Matt Borgerson 2021-04-18 22:17:56 -07:00
parent dc8eab47f6
commit ee18e7bf35
6 changed files with 476 additions and 404 deletions

View File

@ -209,8 +209,8 @@ struct PixelShader {
struct FCInputInfo final_input;
int tex_modes[4], input_tex[4], dot_map[4];
QString *varE, *varF;
QString *code;
MString *varE, *varF;
MString *code;
int cur_stage;
int num_var_refs;
@ -238,63 +238,63 @@ static void add_const_ref(struct PixelShader *ps, const char *var)
}
// Get the code for a variable used in the program
static QString* get_var(struct PixelShader *ps, int reg, bool is_dest)
static MString* get_var(struct PixelShader *ps, int reg, bool is_dest)
{
switch (reg) {
case PS_REGISTER_DISCARD:
if (is_dest) {
return qstring_from_str("");
return mstring_from_str("");
} else {
return qstring_from_str("vec4(0.0)");
return mstring_from_str("vec4(0.0)");
}
break;
case PS_REGISTER_C0:
if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C0 || ps->cur_stage == 8) {
QString *reg = qstring_from_fmt("c0_%d", ps->cur_stage);
add_const_ref(ps, qstring_get_str(reg));
MString *reg = mstring_from_fmt("c0_%d", ps->cur_stage);
add_const_ref(ps, mstring_get_str(reg));
return reg;
} else { // Same c0
add_const_ref(ps, "c0_0");
return qstring_from_str("c0_0");
return mstring_from_str("c0_0");
}
break;
case PS_REGISTER_C1:
if (ps->flags & PS_COMBINERCOUNT_UNIQUE_C1 || ps->cur_stage == 8) {
QString *reg = qstring_from_fmt("c1_%d", ps->cur_stage);
add_const_ref(ps, qstring_get_str(reg));
MString *reg = mstring_from_fmt("c1_%d", ps->cur_stage);
add_const_ref(ps, mstring_get_str(reg));
return reg;
} else { // Same c1
add_const_ref(ps, "c1_0");
return qstring_from_str("c1_0");
return mstring_from_str("c1_0");
}
break;
case PS_REGISTER_FOG:
return qstring_from_str("pFog");
return mstring_from_str("pFog");
case PS_REGISTER_V0:
return qstring_from_str("v0");
return mstring_from_str("v0");
case PS_REGISTER_V1:
return qstring_from_str("v1");
return mstring_from_str("v1");
case PS_REGISTER_T0:
return qstring_from_str("t0");
return mstring_from_str("t0");
case PS_REGISTER_T1:
return qstring_from_str("t1");
return mstring_from_str("t1");
case PS_REGISTER_T2:
return qstring_from_str("t2");
return mstring_from_str("t2");
case PS_REGISTER_T3:
return qstring_from_str("t3");
return mstring_from_str("t3");
case PS_REGISTER_R0:
add_var_ref(ps, "r0");
return qstring_from_str("r0");
return mstring_from_str("r0");
case PS_REGISTER_R1:
add_var_ref(ps, "r1");
return qstring_from_str("r1");
return mstring_from_str("r1");
case PS_REGISTER_V1R0_SUM:
add_var_ref(ps, "r0");
return qstring_from_str("vec4(v1.rgb + r0.rgb, 0.0)");
return mstring_from_str("vec4(v1.rgb + r0.rgb, 0.0)");
case PS_REGISTER_EF_PROD:
return qstring_from_fmt("vec4(%s * %s, 0.0)",
qstring_get_str(ps->varE),
qstring_get_str(ps->varF));
return mstring_from_fmt("vec4(%s * %s, 0.0)",
mstring_get_str(ps->varE),
mstring_get_str(ps->varF));
default:
assert(false);
return NULL;
@ -302,17 +302,17 @@ static QString* get_var(struct PixelShader *ps, int reg, bool is_dest)
}
// Get input variable code
static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool is_alpha)
static MString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool is_alpha)
{
QString *reg = get_var(ps, in.reg, false);
MString *reg = get_var(ps, in.reg, false);
if (!is_alpha) {
switch (in.chan) {
case PS_CHANNEL_RGB:
qstring_append(reg, ".rgb");
mstring_append(reg, ".rgb");
break;
case PS_CHANNEL_ALPHA:
qstring_append(reg, ".aaa");
mstring_append(reg, ".aaa");
break;
default:
assert(false);
@ -321,10 +321,10 @@ static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool
} else {
switch (in.chan) {
case PS_CHANNEL_BLUE:
qstring_append(reg, ".b");
mstring_append(reg, ".b");
break;
case PS_CHANNEL_ALPHA:
qstring_append(reg, ".a");
mstring_append(reg, ".a");
break;
default:
assert(false);
@ -332,65 +332,65 @@ static QString* get_input_var(struct PixelShader *ps, struct InputInfo in, bool
}
}
QString *res;
MString *res;
switch (in.mod) {
case PS_INPUTMAPPING_UNSIGNED_IDENTITY:
res = qstring_from_fmt("max(%s, 0.0)", qstring_get_str(reg));
res = mstring_from_fmt("max(%s, 0.0)", mstring_get_str(reg));
break;
case PS_INPUTMAPPING_UNSIGNED_INVERT:
res = qstring_from_fmt("(1.0 - clamp(%s, 0.0, 1.0))", qstring_get_str(reg));
res = mstring_from_fmt("(1.0 - clamp(%s, 0.0, 1.0))", mstring_get_str(reg));
break;
case PS_INPUTMAPPING_EXPAND_NORMAL:
res = qstring_from_fmt("(2.0 * max(%s, 0.0) - 1.0)", qstring_get_str(reg));
res = mstring_from_fmt("(2.0 * max(%s, 0.0) - 1.0)", mstring_get_str(reg));
break;
case PS_INPUTMAPPING_EXPAND_NEGATE:
res = qstring_from_fmt("(-2.0 * max(%s, 0.0) + 1.0)", qstring_get_str(reg));
res = mstring_from_fmt("(-2.0 * max(%s, 0.0) + 1.0)", mstring_get_str(reg));
break;
case PS_INPUTMAPPING_HALFBIAS_NORMAL:
res = qstring_from_fmt("(max(%s, 0.0) - 0.5)", qstring_get_str(reg));
res = mstring_from_fmt("(max(%s, 0.0) - 0.5)", mstring_get_str(reg));
break;
case PS_INPUTMAPPING_HALFBIAS_NEGATE:
res = qstring_from_fmt("(-max(%s, 0.0) + 0.5)", qstring_get_str(reg));
res = mstring_from_fmt("(-max(%s, 0.0) + 0.5)", mstring_get_str(reg));
break;
case PS_INPUTMAPPING_SIGNED_IDENTITY:
qobject_ref(reg);
mstring_ref(reg);
res = reg;
break;
case PS_INPUTMAPPING_SIGNED_NEGATE:
res = qstring_from_fmt("-%s", qstring_get_str(reg));
res = mstring_from_fmt("-%s", mstring_get_str(reg));
break;
default:
assert(false);
break;
}
qobject_unref(reg);
mstring_unref(reg);
return res;
}
// Get code for the output mapping of a stage
static QString* get_output(QString *reg, int mapping)
static MString* get_output(MString *reg, int mapping)
{
QString *res;
MString *res;
switch (mapping) {
case PS_COMBINEROUTPUT_IDENTITY:
qobject_ref(reg);
mstring_ref(reg);
res = reg;
break;
case PS_COMBINEROUTPUT_BIAS:
res = qstring_from_fmt("(%s - 0.5)", qstring_get_str(reg));
res = mstring_from_fmt("(%s - 0.5)", mstring_get_str(reg));
break;
case PS_COMBINEROUTPUT_SHIFTLEFT_1:
res = qstring_from_fmt("(%s * 2.0)", qstring_get_str(reg));
res = mstring_from_fmt("(%s * 2.0)", mstring_get_str(reg));
break;
case PS_COMBINEROUTPUT_SHIFTLEFT_1_BIAS:
res = qstring_from_fmt("((%s - 0.5) * 2.0)", qstring_get_str(reg));
res = mstring_from_fmt("((%s - 0.5) * 2.0)", mstring_get_str(reg));
break;
case PS_COMBINEROUTPUT_SHIFTLEFT_2:
res = qstring_from_fmt("(%s * 4.0)", qstring_get_str(reg));
res = mstring_from_fmt("(%s * 4.0)", mstring_get_str(reg));
break;
case PS_COMBINEROUTPUT_SHIFTRIGHT_1:
res = qstring_from_fmt("(%s / 2.0)", qstring_get_str(reg));
res = mstring_from_fmt("(%s / 2.0)", mstring_get_str(reg));
break;
default:
assert(false);
@ -404,94 +404,94 @@ static void add_stage_code(struct PixelShader *ps,
struct InputVarInfo input, struct OutputInfo output,
const char *write_mask, bool is_alpha)
{
QString *a = get_input_var(ps, input.a, is_alpha);
QString *b = get_input_var(ps, input.b, is_alpha);
QString *c = get_input_var(ps, input.c, is_alpha);
QString *d = get_input_var(ps, input.d, is_alpha);
MString *a = get_input_var(ps, input.a, is_alpha);
MString *b = get_input_var(ps, input.b, is_alpha);
MString *c = get_input_var(ps, input.c, is_alpha);
MString *d = get_input_var(ps, input.d, is_alpha);
const char *caster = "";
if (strlen(write_mask) == 3) {
caster = "vec3";
}
QString *ab;
MString *ab;
if (output.ab_op == PS_COMBINEROUTPUT_AB_DOT_PRODUCT) {
ab = qstring_from_fmt("dot(%s, %s)",
qstring_get_str(a), qstring_get_str(b));
ab = mstring_from_fmt("dot(%s, %s)",
mstring_get_str(a), mstring_get_str(b));
} else {
ab = qstring_from_fmt("(%s * %s)",
qstring_get_str(a), qstring_get_str(b));
ab = mstring_from_fmt("(%s * %s)",
mstring_get_str(a), mstring_get_str(b));
}
QString *cd;
MString *cd;
if (output.cd_op == PS_COMBINEROUTPUT_CD_DOT_PRODUCT) {
cd = qstring_from_fmt("dot(%s, %s)",
qstring_get_str(c), qstring_get_str(d));
cd = mstring_from_fmt("dot(%s, %s)",
mstring_get_str(c), mstring_get_str(d));
} else {
cd = qstring_from_fmt("(%s * %s)",
qstring_get_str(c), qstring_get_str(d));
cd = mstring_from_fmt("(%s * %s)",
mstring_get_str(c), mstring_get_str(d));
}
QString *ab_mapping = get_output(ab, output.mapping);
QString *cd_mapping = get_output(cd, output.mapping);
QString *ab_dest = get_var(ps, output.ab, true);
QString *cd_dest = get_var(ps, output.cd, true);
QString *sum_dest = get_var(ps, output.muxsum, true);
MString *ab_mapping = get_output(ab, output.mapping);
MString *cd_mapping = get_output(cd, output.mapping);
MString *ab_dest = get_var(ps, output.ab, true);
MString *cd_dest = get_var(ps, output.cd, true);
MString *sum_dest = get_var(ps, output.muxsum, true);
if (qstring_get_length(ab_dest)) {
qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
qstring_get_str(ab_dest), write_mask, caster, qstring_get_str(ab_mapping));
if (mstring_get_length(ab_dest)) {
mstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
mstring_get_str(ab_dest), write_mask, caster, mstring_get_str(ab_mapping));
} else {
qobject_unref(ab_dest);
qobject_ref(ab_mapping);
mstring_unref(ab_dest);
mstring_ref(ab_mapping);
ab_dest = ab_mapping;
}
if (qstring_get_length(cd_dest)) {
qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
qstring_get_str(cd_dest), write_mask, caster, qstring_get_str(cd_mapping));
if (mstring_get_length(cd_dest)) {
mstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
mstring_get_str(cd_dest), write_mask, caster, mstring_get_str(cd_mapping));
} else {
qobject_unref(cd_dest);
qobject_ref(cd_mapping);
mstring_unref(cd_dest);
mstring_ref(cd_mapping);
cd_dest = cd_mapping;
}
if (!is_alpha && output.flags & PS_COMBINEROUTPUT_AB_BLUE_TO_ALPHA) {
qstring_append_fmt(ps->code, "%s.a = %s.b;\n",
qstring_get_str(ab_dest), qstring_get_str(ab_dest));
mstring_append_fmt(ps->code, "%s.a = %s.b;\n",
mstring_get_str(ab_dest), mstring_get_str(ab_dest));
}
if (!is_alpha && output.flags & PS_COMBINEROUTPUT_CD_BLUE_TO_ALPHA) {
qstring_append_fmt(ps->code, "%s.a = %s.b;\n",
qstring_get_str(cd_dest), qstring_get_str(cd_dest));
mstring_append_fmt(ps->code, "%s.a = %s.b;\n",
mstring_get_str(cd_dest), mstring_get_str(cd_dest));
}
QString *sum;
MString *sum;
if (output.muxsum_op == PS_COMBINEROUTPUT_AB_CD_SUM) {
sum = qstring_from_fmt("(%s + %s)", qstring_get_str(ab), qstring_get_str(cd));
sum = mstring_from_fmt("(%s + %s)", mstring_get_str(ab), mstring_get_str(cd));
} else {
sum = qstring_from_fmt("((r0.a >= 0.5) ? %s(%s) : %s(%s))",
caster, qstring_get_str(cd), caster, qstring_get_str(ab));
sum = mstring_from_fmt("((r0.a >= 0.5) ? %s(%s) : %s(%s))",
caster, mstring_get_str(cd), caster, mstring_get_str(ab));
}
QString *sum_mapping = get_output(sum, output.mapping);
if (qstring_get_length(sum_dest)) {
qstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
qstring_get_str(sum_dest), write_mask, caster, qstring_get_str(sum_mapping));
MString *sum_mapping = get_output(sum, output.mapping);
if (mstring_get_length(sum_dest)) {
mstring_append_fmt(ps->code, "%s.%s = clamp(%s(%s), -1.0, 1.0);\n",
mstring_get_str(sum_dest), write_mask, caster, mstring_get_str(sum_mapping));
}
qobject_unref(a);
qobject_unref(b);
qobject_unref(c);
qobject_unref(d);
qobject_unref(ab);
qobject_unref(cd);
qobject_unref(ab_mapping);
qobject_unref(cd_mapping);
qobject_unref(ab_dest);
qobject_unref(cd_dest);
qobject_unref(sum_dest);
qobject_unref(sum);
qobject_unref(sum_mapping);
mstring_unref(a);
mstring_unref(b);
mstring_unref(c);
mstring_unref(d);
mstring_unref(ab);
mstring_unref(cd);
mstring_unref(ab_mapping);
mstring_unref(cd_mapping);
mstring_unref(ab_dest);
mstring_unref(cd_dest);
mstring_unref(sum_dest);
mstring_unref(sum);
mstring_unref(sum_mapping);
}
// Add code for the final combiner stage
@ -500,40 +500,40 @@ static void add_final_stage_code(struct PixelShader *ps, struct FCInputInfo fina
ps->varE = get_input_var(ps, final.e, false);
ps->varF = get_input_var(ps, final.f, false);
QString *a = get_input_var(ps, final.a, false);
QString *b = get_input_var(ps, final.b, false);
QString *c = get_input_var(ps, final.c, false);
QString *d = get_input_var(ps, final.d, false);
QString *g = get_input_var(ps, final.g, true);
MString *a = get_input_var(ps, final.a, false);
MString *b = get_input_var(ps, final.b, false);
MString *c = get_input_var(ps, final.c, false);
MString *d = get_input_var(ps, final.d, false);
MString *g = get_input_var(ps, final.g, true);
qstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n",
qstring_get_str(d), qstring_get_str(c),
qstring_get_str(b), qstring_get_str(a));
qstring_append_fmt(ps->code, "fragColor.a = %s;\n", qstring_get_str(g));
mstring_append_fmt(ps->code, "fragColor.rgb = %s + mix(vec3(%s), vec3(%s), vec3(%s));\n",
mstring_get_str(d), mstring_get_str(c),
mstring_get_str(b), mstring_get_str(a));
mstring_append_fmt(ps->code, "fragColor.a = %s;\n", mstring_get_str(g));
qobject_unref(a);
qobject_unref(b);
qobject_unref(c);
qobject_unref(d);
qobject_unref(g);
mstring_unref(a);
mstring_unref(b);
mstring_unref(c);
mstring_unref(d);
mstring_unref(g);
qobject_unref(ps->varE);
qobject_unref(ps->varF);
mstring_unref(ps->varE);
mstring_unref(ps->varF);
ps->varE = ps->varF = NULL;
}
static QString* psh_convert(struct PixelShader *ps)
static MString* psh_convert(struct PixelShader *ps)
{
int i;
QString *preflight = qstring_new();
qstring_append(preflight, STRUCT_VERTEX_DATA);
qstring_append(preflight, "noperspective in VertexData g_vtx;\n");
qstring_append(preflight, "#define vtx g_vtx\n");
qstring_append(preflight, "\n");
qstring_append(preflight, "out vec4 fragColor;\n");
qstring_append(preflight, "\n");
qstring_append(preflight, "uniform vec4 fogColor;\n");
MString *preflight = mstring_new();
mstring_append(preflight, STRUCT_VERTEX_DATA);
mstring_append(preflight, "noperspective in VertexData g_vtx;\n");
mstring_append(preflight, "#define vtx g_vtx\n");
mstring_append(preflight, "\n");
mstring_append(preflight, "out vec4 fragColor;\n");
mstring_append(preflight, "\n");
mstring_append(preflight, "uniform vec4 fogColor;\n");
const char *dotmap_funcs[] = {
"dotmap_zero_to_one",
@ -546,7 +546,7 @@ static QString* psh_convert(struct PixelShader *ps)
"dotmap_hilo_hemisphere",
};
qstring_append_fmt(preflight,
mstring_append_fmt(preflight,
"float sign1(float x) {\n"
" x *= 255.0;\n"
" return (x-128.0)/127.0;\n"
@ -608,57 +608,57 @@ static QString* psh_convert(struct PixelShader *ps)
);
/* Window Clipping */
QString *clip = qstring_new();
MString *clip = mstring_new();
if (ps->state.window_clip_count != 0) {
qstring_append_fmt(preflight, "uniform ivec4 clipRegion[%d];\n",
mstring_append_fmt(preflight, "uniform ivec4 clipRegion[%d];\n",
ps->state.window_clip_count);
qstring_append_fmt(clip, "/* Window-clip (%s) */\n",
mstring_append_fmt(clip, "/* Window-clip (%s) */\n",
ps->state.window_clip_exclusive ?
"Exclusive" : "Inclusive");
if (!ps->state.window_clip_exclusive) {
qstring_append(clip, "bool clipContained = false;\n");
mstring_append(clip, "bool clipContained = false;\n");
}
qstring_append_fmt(clip, "for (int i = 0; i < %d; i++) {\n",
mstring_append_fmt(clip, "for (int i = 0; i < %d; i++) {\n",
ps->state.window_clip_count);
qstring_append(clip, " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy, clipRegion[i].xy),\n"
mstring_append(clip, " bvec4 clipTest = bvec4(lessThan(gl_FragCoord.xy, clipRegion[i].xy),\n"
" greaterThan(gl_FragCoord.xy, clipRegion[i].zw));\n"
" if (!any(clipTest)) {\n");
if (ps->state.window_clip_exclusive) {
/* Pixel in clip region = exclude by discarding */
qstring_append(clip, " discard;\n");
mstring_append(clip, " discard;\n");
assert(false); /* Untested */
} else {
/* Pixel in clip region = mark pixel as contained and leave */
qstring_append(clip, " clipContained = true;\n"
mstring_append(clip, " clipContained = true;\n"
" break;\n");
}
qstring_append(clip, " }\n"
mstring_append(clip, " }\n"
"}\n");
/* Check for inclusive window clip */
if (!ps->state.window_clip_exclusive) {
qstring_append(clip, "if (!clipContained) { discard; }\n");
mstring_append(clip, "if (!clipContained) { discard; }\n");
}
} else if (ps->state.window_clip_exclusive) {
/* Clip everything */
qstring_append(clip, "discard;\n");
mstring_append(clip, "discard;\n");
}
/* calculate perspective-correct inputs */
QString *vars = qstring_new();
qstring_append(vars, "vec4 pD0 = vtx.D0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n");
qstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n");
qstring_append(vars, "vec4 pT3 = vtx.T3 / vtx.inv_w;\n");
qstring_append(vars, "\n");
qstring_append(vars, "vec4 v0 = pD0;\n");
qstring_append(vars, "vec4 v1 = pD1;\n");
MString *vars = mstring_new();
mstring_append(vars, "vec4 pD0 = vtx.D0 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pD1 = vtx.D1 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pB0 = vtx.B0 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pB1 = vtx.B1 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pFog = vec4(fogColor.rgb, clamp(vtx.Fog / vtx.inv_w, 0.0, 1.0));\n");
mstring_append(vars, "vec4 pT0 = vtx.T0 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pT1 = vtx.T1 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pT2 = vtx.T2 / vtx.inv_w;\n");
mstring_append(vars, "vec4 pT3 = vtx.T3 / vtx.inv_w;\n");
mstring_append(vars, "\n");
mstring_append(vars, "vec4 v0 = pD0;\n");
mstring_append(vars, "vec4 v1 = pD1;\n");
ps->code = qstring_new();
ps->code = mstring_new();
for (i = 0; i < 4; i++) {
@ -672,7 +672,7 @@ static QString* psh_convert(struct PixelShader *ps)
switch (ps->tex_modes[i]) {
case PS_TEXTUREMODES_NONE:
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n",
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_NONE */\n",
i);
break;
case PS_TEXTUREMODES_PROJECT2D: {
@ -690,29 +690,29 @@ static QString* psh_convert(struct PixelShader *ps)
NV2A_UNIMPLEMENTED("Convolution for 2D textures");
}
}
qstring_append_fmt(vars, "vec4 t%d = %s(texSamp%d, pT%d.xyw);\n",
mstring_append_fmt(vars, "vec4 t%d = %s(texSamp%d, pT%d.xyw);\n",
i, lookup, i, i);
break;
}
case PS_TEXTUREMODES_PROJECT3D:
sampler_type = "sampler3D";
qstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
mstring_append_fmt(vars, "vec4 t%d = textureProj(texSamp%d, pT%d.xyzw);\n",
i, i, i);
break;
case PS_TEXTUREMODES_CUBEMAP:
sampler_type = "samplerCube";
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz / pT%d.w);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xyz / pT%d.w);\n",
i, i, i, i);
break;
case PS_TEXTUREMODES_PASSTHRU:
qstring_append_fmt(vars, "vec4 t%d = pT%d;\n", i, i);
mstring_append_fmt(vars, "vec4 t%d = pT%d;\n", i, i);
break;
case PS_TEXTUREMODES_CLIPPLANE: {
int j;
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_CLIPPLANE */\n",
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_CLIPPLANE */\n",
i);
for (j = 0; j < 4; j++) {
qstring_append_fmt(vars, " if(pT%d.%c %s 0.0) { discard; };\n",
mstring_append_fmt(vars, " if(pT%d.%c %s 0.0) { discard; };\n",
i, "xyzw"[j],
ps->state.compare_mode[i][j] ? ">=" : "<");
}
@ -721,143 +721,143 @@ static QString* psh_convert(struct PixelShader *ps)
case PS_TEXTUREMODES_BUMPENVMAP:
assert(i >= 1);
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
qstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
if (ps->state.snorm_tex[ps->input_tex[i]]) {
/* Input color channels already signed (FIXME: May not always want signed textures in this case) */
qstring_append_fmt(vars, "vec2 dsdt%d = t%d.bg;\n",
mstring_append_fmt(vars, "vec2 dsdt%d = t%d.bg;\n",
i, ps->input_tex[i]);
} else {
/* Convert to signed (FIXME: loss of accuracy due to filtering/interpolation) */
qstring_append_fmt(vars, "vec2 dsdt%d = vec2(sign3(t%d.b), sign3(t%d.g));\n",
mstring_append_fmt(vars, "vec2 dsdt%d = vec2(sign3(t%d.b), sign3(t%d.g));\n",
i, ps->input_tex[i], ps->input_tex[i]);
}
/* FIXME: Do bumpMat swizzle on CPU before upload */
qstring_append_fmt(vars, "dsdt%d = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdt%d;\n",
mstring_append_fmt(vars, "dsdt%d = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdt%d;\n",
i, i, i, i);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdt%d);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdt%d);\n",
i, i, i, i);
break;
case PS_TEXTUREMODES_BUMPENVMAP_LUM:
assert(i >= 1);
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
qstring_append_fmt(preflight, "uniform float bumpScale%d;\n", i);
qstring_append_fmt(preflight, "uniform float bumpOffset%d;\n", i);
qstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
mstring_append_fmt(preflight, "uniform float bumpScale%d;\n", i);
mstring_append_fmt(preflight, "uniform float bumpOffset%d;\n", i);
mstring_append_fmt(preflight, "uniform mat2 bumpMat%d;\n", i);
if (ps->state.snorm_tex[ps->input_tex[i]]) {
/* Input color channels already signed (FIXME: May not always want signed textures in this case) */
qstring_append_fmt(vars, "vec3 dsdtl%d = vec3(t%d.bg, sign3_to_0_to_1(t%d.r));\n",
mstring_append_fmt(vars, "vec3 dsdtl%d = vec3(t%d.bg, sign3_to_0_to_1(t%d.r));\n",
i, ps->input_tex[i], ps->input_tex[i]);
} else {
/* Convert to signed (FIXME: loss of accuracy due to filtering/interpolation) */
qstring_append_fmt(vars, "vec3 dsdtl%d = vec3(sign3(t%d.b), sign3(t%d.g), t%d.r);\n",
mstring_append_fmt(vars, "vec3 dsdtl%d = vec3(sign3(t%d.b), sign3(t%d.g), t%d.r);\n",
i, ps->input_tex[i], ps->input_tex[i], ps->input_tex[i]);
}
/* FIXME: Do bumpMat swizzle on CPU before upload */
qstring_append_fmt(vars, "dsdtl%d.st = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdtl%d.st;\n",
mstring_append_fmt(vars, "dsdtl%d.st = mat2(bumpMat%d[0].xy, bumpMat%d[1].yx) * dsdtl%d.st;\n",
i, i, i, i);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdtl%d.st);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, pT%d.xy + dsdtl%d.st);\n",
i, i, i, i);
qstring_append_fmt(vars, "t%d = t%d * (bumpScale%d * dsdtl%d.p + bumpOffset%d);\n",
mstring_append_fmt(vars, "t%d = t%d * (bumpScale%d * dsdtl%d.p + bumpOffset%d);\n",
i, i, i, i, i);
break;
case PS_TEXTUREMODES_BRDF:
assert(i >= 2);
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_BRDF */\n",
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_BRDF */\n",
i);
NV2A_UNIMPLEMENTED("PS_TEXTUREMODES_BRDF");
break;
case PS_TEXTUREMODES_DOT_ST:
assert(i >= 2);
sampler_type = ps->state.rect_tex[i] ? "sampler2DRect" : "sampler2D";
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ST */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ST */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec2(dot%d, dot%d));\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec2(dot%d, dot%d));\n",
i, i, i-1, i);
break;
case PS_TEXTUREMODES_DOT_ZW:
assert(i >= 2);
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ZW */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_ZW */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
// FIXME: qstring_append_fmt(vars, "gl_FragDepth = t%d.x;\n", i);
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
// FIXME: mstring_append_fmt(vars, "gl_FragDepth = t%d.x;\n", i);
break;
case PS_TEXTUREMODES_DOT_RFLCT_DIFF:
assert(i == 2);
sampler_type = "samplerCube";
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_DIFF */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_DIFF */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
assert(ps->dot_map[i+1] < 8);
qstring_append_fmt(vars, "float dot%d_n = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "float dot%d_n = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i+1, dotmap_funcs[ps->dot_map[i+1]], ps->input_tex[i+1]);
qstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d_n);\n",
mstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d_n);\n",
i, i-1, i, i);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, n_%d);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, n_%d);\n",
i, i, i);
break;
case PS_TEXTUREMODES_DOT_RFLCT_SPEC:
assert(i == 3);
sampler_type = "samplerCube";
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_SPEC */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_RFLCT_SPEC */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
qstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d);\n",
mstring_append_fmt(vars, "vec3 n_%d = vec3(dot%d, dot%d, dot%d);\n",
i, i-2, i-1, i);
qstring_append_fmt(vars, "vec3 e_%d = vec3(pT%d.w, pT%d.w, pT%d.w);\n",
mstring_append_fmt(vars, "vec3 e_%d = vec3(pT%d.w, pT%d.w, pT%d.w);\n",
i, i-2, i-1, i);
qstring_append_fmt(vars, "vec3 rv_%d = 2*n_%d*dot(n_%d,e_%d)/dot(n_%d,n_%d) - e_%d;\n",
mstring_append_fmt(vars, "vec3 rv_%d = 2*n_%d*dot(n_%d,e_%d)/dot(n_%d,n_%d) - e_%d;\n",
i, i, i, i, i, i, i);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, rv_%d);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, rv_%d);\n",
i, i, i);
break;
case PS_TEXTUREMODES_DOT_STR_3D:
assert(i == 3);
sampler_type = "sampler3D";
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_3D */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_3D */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
i, i, i-2, i-1, i);
break;
case PS_TEXTUREMODES_DOT_STR_CUBE:
assert(i == 3);
sampler_type = "samplerCube";
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_CUBE */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOT_STR_CUBE */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, vec3(dot%d, dot%d, dot%d));\n",
i, i, i-2, i-1, i);
break;
case PS_TEXTUREMODES_DPNDNT_AR:
assert(i >= 1);
assert(!ps->state.rect_tex[i]);
sampler_type = "sampler2D";
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.ar);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.ar);\n",
i, i, ps->input_tex[i]);
break;
case PS_TEXTUREMODES_DPNDNT_GB:
assert(i >= 1);
assert(!ps->state.rect_tex[i]);
sampler_type = "sampler2D";
qstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.gb);\n",
mstring_append_fmt(vars, "vec4 t%d = texture(texSamp%d, t%d.gb);\n",
i, i, ps->input_tex[i]);
break;
case PS_TEXTUREMODES_DOTPRODUCT:
assert(i == 1 || i == 2);
qstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOTPRODUCT */\n");
qstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
mstring_append_fmt(vars, "/* PS_TEXTUREMODES_DOTPRODUCT */\n");
mstring_append_fmt(vars, "float dot%d = dot(pT%d.xyz, %s(t%d.rgb));\n",
i, i, dotmap_func, ps->input_tex[i]);
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0);\n", i);
break;
case PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST:
assert(i == 3);
qstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST */\n",
mstring_append_fmt(vars, "vec4 t%d = vec4(0.0); /* PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST */\n",
i);
NV2A_UNIMPLEMENTED("PS_TEXTUREMODES_DOT_RFLCT_SPEC_CONST");
break;
@ -868,11 +868,11 @@ static QString* psh_convert(struct PixelShader *ps)
}
if (sampler_type != NULL) {
qstring_append_fmt(preflight, "uniform %s texSamp%d;\n", sampler_type, i);
mstring_append_fmt(preflight, "uniform %s texSamp%d;\n", sampler_type, i);
/* As this means a texture fetch does happen, do alphakill */
if (ps->state.alphakill[i]) {
qstring_append_fmt(vars, "if (t%d.a == 0.0) { discard; };\n",
mstring_append_fmt(vars, "if (t%d.a == 0.0) { discard; };\n",
i);
}
}
@ -880,21 +880,21 @@ static QString* psh_convert(struct PixelShader *ps)
for (i = 0; i < ps->num_stages; i++) {
ps->cur_stage = i;
qstring_append_fmt(ps->code, "// Stage %d\n", i);
mstring_append_fmt(ps->code, "// Stage %d\n", i);
add_stage_code(ps, ps->stage[i].rgb_input, ps->stage[i].rgb_output, "rgb", false);
add_stage_code(ps, ps->stage[i].alpha_input, ps->stage[i].alpha_output, "a", true);
}
if (ps->final_input.enabled) {
ps->cur_stage = 8;
qstring_append(ps->code, "// Final Combiner\n");
mstring_append(ps->code, "// Final Combiner\n");
add_final_stage_code(ps, ps->final_input);
}
if (ps->state.alpha_test && ps->state.alpha_func != ALPHA_FUNC_ALWAYS) {
qstring_append_fmt(preflight, "uniform float alphaRef;\n");
mstring_append_fmt(preflight, "uniform float alphaRef;\n");
if (ps->state.alpha_func == ALPHA_FUNC_NEVER) {
qstring_append(ps->code, "discard;\n");
mstring_append(ps->code, "discard;\n");
} else {
const char* alpha_op;
switch (ps->state.alpha_func) {
@ -908,38 +908,38 @@ static QString* psh_convert(struct PixelShader *ps)
assert(false);
break;
}
qstring_append_fmt(ps->code, "if (!(fragColor.a %s alphaRef)) discard;\n",
mstring_append_fmt(ps->code, "if (!(fragColor.a %s alphaRef)) discard;\n",
alpha_op);
}
}
for (i = 0; i < ps->num_const_refs; i++) {
qstring_append_fmt(preflight, "uniform vec4 %s;\n", ps->const_refs[i]);
mstring_append_fmt(preflight, "uniform vec4 %s;\n", ps->const_refs[i]);
}
for (i = 0; i < ps->num_var_refs; i++) {
qstring_append_fmt(vars, "vec4 %s;\n", ps->var_refs[i]);
mstring_append_fmt(vars, "vec4 %s;\n", ps->var_refs[i]);
if (strcmp(ps->var_refs[i], "r0") == 0) {
if (ps->tex_modes[0] != PS_TEXTUREMODES_NONE) {
qstring_append(vars, "r0.a = t0.a;\n");
mstring_append(vars, "r0.a = t0.a;\n");
} else {
qstring_append(vars, "r0.a = 1.0;\n");
mstring_append(vars, "r0.a = 1.0;\n");
}
}
}
QString *final = qstring_new();
qstring_append(final, "#version 330\n\n");
qstring_append(final, qstring_get_str(preflight));
qstring_append(final, "void main() {\n");
qstring_append(final, qstring_get_str(clip));
qstring_append(final, qstring_get_str(vars));
qstring_append(final, qstring_get_str(ps->code));
qstring_append(final, "}\n");
MString *final = mstring_new();
mstring_append(final, "#version 330\n\n");
mstring_append(final, mstring_get_str(preflight));
mstring_append(final, "void main() {\n");
mstring_append(final, mstring_get_str(clip));
mstring_append(final, mstring_get_str(vars));
mstring_append(final, mstring_get_str(ps->code));
mstring_append(final, "}\n");
qobject_unref(preflight);
qobject_unref(vars);
qobject_unref(ps->code);
mstring_unref(preflight);
mstring_unref(vars);
mstring_unref(ps->code);
return final;
}
@ -976,7 +976,7 @@ static void parse_combiner_output(uint32_t value, struct OutputInfo *out)
out->cd_alphablue = flags & 0x40;
}
QString *psh_translate(const PshState state)
MString *psh_translate(const PshState state)
{
int i;
struct PixelShader ps;

View File

@ -20,7 +20,7 @@
#ifndef HW_NV2A_PSH_H
#define HW_NV2A_PSH_H
#include "qapi/qmp/qstring.h"
#include "shaders_common.h"
enum PshAlphaFunc {
ALPHA_FUNC_NEVER,
@ -63,6 +63,6 @@ typedef struct PshState {
unsigned int window_clip_count;
} PshState;
QString *psh_translate(const PshState state);
MString *psh_translate(const PshState state);
#endif

View File

@ -25,26 +25,26 @@
#include "shaders_common.h"
#include "shaders.h"
void qstring_append_fmt(QString *qstring, const char *fmt, ...)
void mstring_append_fmt(MString *qstring, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
qstring_append_va(qstring, fmt, ap);
mstring_append_va(qstring, fmt, ap);
va_end(ap);
}
QString *qstring_from_fmt(const char *fmt, ...)
MString *mstring_from_fmt(const char *fmt, ...)
{
QString *ret = qstring_new();
MString *ret = mstring_new();
va_list ap;
va_start(ap, fmt);
qstring_append_va(ret, fmt, ap);
mstring_append_va(ret, fmt, ap);
va_end(ap);
return ret;
}
void qstring_append_va(QString *qstring, const char *fmt, va_list va)
void mstring_append_va(MString *qstring, const char *fmt, va_list va)
{
char scratch[256];
@ -56,7 +56,7 @@ void qstring_append_va(QString *qstring, const char *fmt, va_list va)
if (len == 0) {
return;
} else if (len < sizeof(scratch)) {
qstring_append(qstring, scratch);
mstring_append(qstring, scratch);
return;
}
@ -66,11 +66,11 @@ void qstring_append_va(QString *qstring, const char *fmt, va_list va)
vsnprintf(buf, len + 1, fmt, ap);
va_end(ap);
qstring_append(qstring, buf);
mstring_append(qstring, buf);
g_free(buf);
}
static QString* generate_geometry_shader(
static MString* generate_geometry_shader(
enum ShaderPolygonMode polygon_front_mode,
enum ShaderPolygonMode polygon_back_mode,
enum ShaderPrimitiveMode primitive_mode,
@ -212,11 +212,11 @@ static QString* generate_geometry_shader(
assert(layout_in);
assert(layout_out);
assert(body);
QString* s = qstring_from_str("#version 330\n"
MString* s = mstring_from_str("#version 330\n"
"\n");
qstring_append(s, layout_in);
qstring_append(s, layout_out);
qstring_append(s, "\n"
mstring_append(s, layout_in);
mstring_append(s, layout_out);
mstring_append(s, "\n"
STRUCT_VERTEX_DATA
"noperspective in VertexData v_vtx[];\n"
"noperspective out VertexData g_vtx;\n"
@ -229,48 +229,48 @@ static QString* generate_geometry_shader(
"}\n"
"\n"
"void main() {\n");
qstring_append(s, body);
qstring_append(s, "}\n");
mstring_append(s, body);
mstring_append(s, "}\n");
return s;
}
static void append_skinning_code(QString* str, bool mix,
static void append_skinning_code(MString* str, bool mix,
unsigned int count, const char* type,
const char* output, const char* input,
const char* matrix, const char* swizzle)
{
if (count == 0) {
qstring_append_fmt(str, "%s %s = (%s * %s0).%s;\n",
mstring_append_fmt(str, "%s %s = (%s * %s0).%s;\n",
type, output, input, matrix, swizzle);
} else {
qstring_append_fmt(str, "%s %s = %s(0.0);\n", type, output, type);
mstring_append_fmt(str, "%s %s = %s(0.0);\n", type, output, type);
if (mix) {
/* Generated final weight (like GL_WEIGHT_SUM_UNITY_ARB) */
qstring_append(str, "{\n"
mstring_append(str, "{\n"
" float weight_i;\n"
" float weight_n = 1.0;\n");
int i;
for (i = 0; i < count; i++) {
if (i < (count - 1)) {
char c = "xyzw"[i];
qstring_append_fmt(str, " weight_i = weight.%c;\n"
mstring_append_fmt(str, " weight_i = weight.%c;\n"
" weight_n -= weight_i;\n",
c);
} else {
qstring_append(str, " weight_i = weight_n;\n");
mstring_append(str, " weight_i = weight_n;\n");
}
qstring_append_fmt(str, " %s += (%s * %s%d).%s * weight_i;\n",
mstring_append_fmt(str, " %s += (%s * %s%d).%s * weight_i;\n",
output, input, matrix, i, swizzle);
}
qstring_append(str, "}\n");
mstring_append(str, "}\n");
} else {
/* Individual weights */
int i;
for (i = 0; i < count; i++) {
char c = "xyzw"[i];
qstring_append_fmt(str, "%s += (%s * %s%d).%s * weight.%c;\n",
mstring_append_fmt(str, "%s += (%s * %s%d).%s * weight.%c;\n",
output, input, matrix, i, swizzle, c);
}
assert(false); /* FIXME: Untested */
@ -288,12 +288,12 @@ static void append_skinning_code(QString* str, bool mix,
#define GLSL_DEFINE(a, b) "#define " stringify(a) " " b "\n"
static void generate_fixed_function(const ShaderState state,
QString *header, QString *body)
MString *header, MString *body)
{
int i, j;
/* generate vertex shader mimicking fixed function */
qstring_append(header,
mstring_append(header,
"#define position v0\n"
"#define weight v1\n"
"#define normal v2.xyz\n"
@ -393,7 +393,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
assert(false);
break;
}
qstring_append_fmt(body, "/* Skinning mode %d */\n",
mstring_append_fmt(body, "/* Skinning mode %d */\n",
state.skinning);
append_skinning_code(body, mix, count, "vec4",
@ -405,12 +405,12 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* Normalization */
if (state.normalization) {
qstring_append(body, "tNormal = normalize(tNormal);\n");
mstring_append(body, "tNormal = normalize(tNormal);\n");
}
/* Texgen */
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
qstring_append_fmt(body, "/* Texgen for stage %d */\n",
mstring_append_fmt(body, "/* Texgen for stage %d */\n",
i);
/* Set each component individually */
/* FIXME: could be nicer if some channels share the same texgen */
@ -420,25 +420,25 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
char cSuffix = "STRQ"[j];
switch (state.texgen[i][j]) {
case TEXGEN_DISABLE:
qstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n",
mstring_append_fmt(body, "oT%d.%c = texture%d.%c;\n",
i, c, i, c);
break;
case TEXGEN_EYE_LINEAR:
qstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, tPosition);\n",
mstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, tPosition);\n",
i, c, cSuffix, i);
break;
case TEXGEN_OBJECT_LINEAR:
qstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, position);\n",
mstring_append_fmt(body, "oT%d.%c = dot(texPlane%c%d, position);\n",
i, c, cSuffix, i);
assert(false); /* Untested */
break;
case TEXGEN_SPHERE_MAP:
assert(j < 2); /* Channels S,T only! */
qstring_append(body, "{\n");
mstring_append(body, "{\n");
/* FIXME: u, r and m only have to be calculated once */
qstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
mstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
//FIXME: tNormal before or after normalization? Always normalize?
qstring_append(body, " vec3 r = reflect(u, tNormal);\n");
mstring_append(body, " vec3 r = reflect(u, tNormal);\n");
/* FIXME: This would consume 1 division fewer and *might* be
* faster than length:
@ -447,24 +447,24 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
* float m = inversesqrt(dot(ro,ro))*0.5;
*/
qstring_append(body, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n");
qstring_append_fmt(body, " oT%d.%c = r.%c * invM + 0.5;\n",
mstring_append(body, " float invM = 1.0 / (2.0 * length(r + vec3(0.0, 0.0, 1.0)));\n");
mstring_append_fmt(body, " oT%d.%c = r.%c * invM + 0.5;\n",
i, c, c);
qstring_append(body, "}\n");
mstring_append(body, "}\n");
break;
case TEXGEN_REFLECTION_MAP:
assert(j < 3); /* Channels S,T,R only! */
qstring_append(body, "{\n");
mstring_append(body, "{\n");
/* FIXME: u and r only have to be calculated once, can share the one from SPHERE_MAP */
qstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
qstring_append(body, " vec3 r = reflect(u, tNormal);\n");
qstring_append_fmt(body, " oT%d.%c = r.%c;\n",
mstring_append(body, " vec3 u = normalize(tPosition.xyz);\n");
mstring_append(body, " vec3 r = reflect(u, tNormal);\n");
mstring_append_fmt(body, " oT%d.%c = r.%c;\n",
i, c, c);
qstring_append(body, "}\n");
mstring_append(body, "}\n");
break;
case TEXGEN_NORMAL_MAP:
assert(j < 3); /* Channels S,T,R only! */
qstring_append_fmt(body, "oT%d.%c = tNormal.%c;\n",
mstring_append_fmt(body, "oT%d.%c = tNormal.%c;\n",
i, c, c);
break;
default:
@ -477,7 +477,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* Apply texture matrices */
for (i = 0; i < NV2A_MAX_TEXTURES; i++) {
if (state.texture_matrix_enable[i]) {
qstring_append_fmt(body,
mstring_append_fmt(body,
"oT%d = oT%d * texMat%d;\n",
i, i, i);
}
@ -489,23 +489,23 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
//FIXME: Do 2 passes if we want 2 sided-lighting?
if (state.ambient_src == MATERIAL_COLOR_SRC_MATERIAL) {
qstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n");
mstring_append(body, "oD0 = vec4(sceneAmbientColor, diffuse.a);\n");
} else if (state.ambient_src == MATERIAL_COLOR_SRC_DIFFUSE) {
qstring_append(body, "oD0 = vec4(diffuse.rgb, diffuse.a);\n");
mstring_append(body, "oD0 = vec4(diffuse.rgb, diffuse.a);\n");
} else if (state.ambient_src == MATERIAL_COLOR_SRC_SPECULAR) {
qstring_append(body, "oD0 = vec4(specular.rgb, diffuse.a);\n");
mstring_append(body, "oD0 = vec4(specular.rgb, diffuse.a);\n");
}
qstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n");
mstring_append(body, "oD0.rgb *= materialEmissionColor.rgb;\n");
if (state.emission_src == MATERIAL_COLOR_SRC_MATERIAL) {
qstring_append(body, "oD0.rgb += sceneAmbientColor;\n");
mstring_append(body, "oD0.rgb += sceneAmbientColor;\n");
} else if (state.emission_src == MATERIAL_COLOR_SRC_DIFFUSE) {
qstring_append(body, "oD0.rgb += diffuse.rgb;\n");
mstring_append(body, "oD0.rgb += diffuse.rgb;\n");
} else if (state.emission_src == MATERIAL_COLOR_SRC_SPECULAR) {
qstring_append(body, "oD0.rgb += specular.rgb;\n");
mstring_append(body, "oD0.rgb += specular.rgb;\n");
}
qstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
mstring_append(body, "oD1 = vec4(0.0, 0.0, 0.0, specular.a);\n");
for (i = 0; i < NV2A_MAX_LIGHTS; i++) {
if (state.light[i] == LIGHT_OFF) {
@ -518,16 +518,16 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
* colors
*/
qstring_append_fmt(body, "/* Light %d */ {\n", i);
mstring_append_fmt(body, "/* Light %d */ {\n", i);
if (state.light[i] == LIGHT_LOCAL
|| state.light[i] == LIGHT_SPOT) {
qstring_append_fmt(header,
mstring_append_fmt(header,
"uniform vec3 lightLocalPosition%d;\n"
"uniform vec3 lightLocalAttenuation%d;\n",
i, i);
qstring_append_fmt(body,
mstring_append_fmt(body,
" vec3 VP = lightLocalPosition%d - tPosition.xyz/tPosition.w;\n"
" float d = length(VP);\n"
//FIXME: if (d > lightLocalRange) { .. don't process this light .. } /* inclusive?! */ - what about directional lights?
@ -547,11 +547,11 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* lightLocalRange will be 1e+30 here */
qstring_append_fmt(header,
mstring_append_fmt(header,
"uniform vec3 lightInfiniteHalfVector%d;\n"
"uniform vec3 lightInfiniteDirection%d;\n",
i, i);
qstring_append_fmt(body,
mstring_append_fmt(body,
" float attenuation = 1.0;\n"
" float nDotVP = max(0.0, dot(tNormal, normalize(vec3(lightInfiniteDirection%d))));\n"
" float nDotHV = max(0.0, dot(tNormal, vec3(lightInfiniteHalfVector%d)));\n",
@ -574,7 +574,7 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
break;
}
qstring_append_fmt(body,
mstring_append_fmt(body,
" float pf;\n"
" if (nDotVP == 0.0) {\n"
" pf = 0.0;\n"
@ -586,23 +586,23 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
" vec3 lightSpecular = lightSpecularColor(%d) * pf;\n",
i, i, i);
qstring_append(body,
mstring_append(body,
" oD0.xyz += lightAmbient;\n");
qstring_append(body,
mstring_append(body,
" oD0.xyz += diffuse.xyz * lightDiffuse;\n");
qstring_append(body,
mstring_append(body,
" oD1.xyz += specular.xyz * lightSpecular;\n");
qstring_append(body, "}\n");
mstring_append(body, "}\n");
}
} else {
qstring_append(body, " oD0 = diffuse;\n");
qstring_append(body, " oD1 = specular;\n");
mstring_append(body, " oD0 = diffuse;\n");
mstring_append(body, " oD1 = specular;\n");
}
qstring_append(body, " oB0 = backDiffuse;\n");
qstring_append(body, " oB1 = backSpecular;\n");
mstring_append(body, " oB0 = backDiffuse;\n");
mstring_append(body, " oB1 = backSpecular;\n");
/* Fog */
if (state.fog_enable) {
@ -611,20 +611,20 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
switch(state.foggen) {
case FOGGEN_SPEC_ALPHA:
/* FIXME: Do we have to clamp here? */
qstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
mstring_append(body, " float fogDistance = clamp(specular.a, 0.0, 1.0);\n");
break;
case FOGGEN_RADIAL:
qstring_append(body, " float fogDistance = length(tPosition.xyz);\n");
mstring_append(body, " float fogDistance = length(tPosition.xyz);\n");
break;
case FOGGEN_PLANAR:
case FOGGEN_ABS_PLANAR:
qstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
mstring_append(body, " float fogDistance = dot(fogPlane.xyz, tPosition.xyz) + fogPlane.w;\n");
if (state.foggen == FOGGEN_ABS_PLANAR) {
qstring_append(body, " fogDistance = abs(fogDistance);\n");
mstring_append(body, " fogDistance = abs(fogDistance);\n");
}
break;
case FOGGEN_FOG_X:
qstring_append(body, " float fogDistance = fogCoord;\n");
mstring_append(body, " float fogDistance = fogCoord;\n");
break;
default:
assert(false);
@ -635,22 +635,22 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz
/* If skinning is off the composite matrix already includes the MV matrix */
if (state.skinning == SKINNING_OFF) {
qstring_append(body, " tPosition = position;\n");
mstring_append(body, " tPosition = position;\n");
}
qstring_append(body,
mstring_append(body,
" oPos = invViewport * (tPosition * compositeMat);\n"
" oPos.z = oPos.z * 2.0 - oPos.w;\n");
qstring_append(body, " vtx.inv_w = 1.0 / oPos.w;\n");
mstring_append(body, " vtx.inv_w = 1.0 / oPos.w;\n");
}
static QString *generate_vertex_shader(const ShaderState state,
static MString *generate_vertex_shader(const ShaderState state,
char vtx_prefix)
{
int i;
QString *header = qstring_from_str(
MString *header = mstring_from_str(
"#version 400\n"
"\n"
"uniform vec2 clipRange;\n"
@ -704,27 +704,27 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT))
"}\n"
STRUCT_VERTEX_DATA);
qstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n",
mstring_append_fmt(header, "noperspective out VertexData %c_vtx;\n",
vtx_prefix);
qstring_append_fmt(header, "#define vtx %c_vtx\n",
mstring_append_fmt(header, "#define vtx %c_vtx\n",
vtx_prefix);
qstring_append(header, "\n");
mstring_append(header, "\n");
for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) {
if (state.compressed_attrs & (1 << i)) {
qstring_append_fmt(header,
mstring_append_fmt(header,
"layout(location = %d) in int v%d_cmp;\n", i, i);
} else {
qstring_append_fmt(header, "layout(location = %d) in vec4 v%d;\n",
mstring_append_fmt(header, "layout(location = %d) in vec4 v%d;\n",
i, i);
}
}
qstring_append(header, "\n");
mstring_append(header, "\n");
QString *body = qstring_from_str("void main() {\n");
MString *body = mstring_from_str("void main() {\n");
for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) {
if (state.compressed_attrs & (1 << i)) {
qstring_append_fmt(
mstring_append_fmt(
body, "vec4 v%d = decompress_11_11_10(v%d_cmp);\n", i, i);
}
}
@ -754,7 +754,7 @@ STRUCT_VERTEX_DATA);
* state.vertex_program = true; state.foggen == FOGGEN_PLANAR
* but expects oFog.x as fogdistance?! Writes oFog.xyzw = v0.z
*/
qstring_append(body, " float fogDistance = oFog.x;\n");
mstring_append(body, " float fogDistance = oFog.x;\n");
}
/* FIXME: Do this per pixel? */
@ -768,8 +768,8 @@ STRUCT_VERTEX_DATA);
* fogParam[0] = 1 + end * fogParam[1];
*/
qstring_append(body, " float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n");
qstring_append(body, " fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */
mstring_append(body, " float fogFactor = fogParam[0] + fogDistance * fogParam[1];\n");
mstring_append(body, " fogFactor -= 1.0;\n"); /* FIXME: WHHYYY?!! */
break;
case FOG_MODE_EXP:
case FOG_MODE_EXP_ABS:
@ -779,8 +779,8 @@ STRUCT_VERTEX_DATA);
* fogParam[0] = 1.5
*/
qstring_append(body, " float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n");
qstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
mstring_append(body, " float fogFactor = fogParam[0] + exp2(fogDistance * fogParam[1] * 16.0);\n");
mstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
break;
case FOG_MODE_EXP2:
case FOG_MODE_EXP2_ABS:
@ -790,8 +790,8 @@ STRUCT_VERTEX_DATA);
* fogParam[0] = 1.5
*/
qstring_append(body, " float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n");
qstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
mstring_append(body, " float fogFactor = fogParam[0] + exp2(-fogDistance * fogDistance * fogParam[1] * fogParam[1] * 32.0);\n");
mstring_append(body, " fogFactor -= 1.5;\n"); /* FIXME: WHHYYY?!! */
break;
default:
assert(false);
@ -802,21 +802,21 @@ STRUCT_VERTEX_DATA);
case FOG_MODE_LINEAR_ABS:
case FOG_MODE_EXP_ABS:
case FOG_MODE_EXP2_ABS:
qstring_append(body, " fogFactor = abs(fogFactor);\n");
mstring_append(body, " fogFactor = abs(fogFactor);\n");
break;
default:
break;
}
/* FIXME: What about fog alpha?! */
qstring_append(body, " oFog.xyzw = vec4(fogFactor);\n");
mstring_append(body, " oFog.xyzw = vec4(fogFactor);\n");
} else {
/* FIXME: Is the fog still calculated / passed somehow?!
*/
qstring_append(body, " oFog.xyzw = vec4(1.0);\n");
mstring_append(body, " oFog.xyzw = vec4(1.0);\n");
}
/* Set outputs */
qstring_append(body, "\n"
mstring_append(body, "\n"
" vtx.D0 = clamp(oD0, 0.0, 1.0) * vtx.inv_w;\n"
" vtx.D1 = clamp(oD1, 0.0, 1.0) * vtx.inv_w;\n"
" vtx.B0 = clamp(oB0, 0.0, 1.0) * vtx.inv_w;\n"
@ -833,8 +833,8 @@ STRUCT_VERTEX_DATA);
/* Return combined header + source */
qstring_append(header, qstring_get_str(body));
qobject_unref(body);
mstring_append(header, mstring_get_str(body));
mstring_unref(body);
return header;
}
@ -884,40 +884,40 @@ ShaderBinding* generate_shaders(const ShaderState state)
/* Create an option geometry shader and find primitive type */
GLenum gl_primitive_mode;
QString* geometry_shader_code =
MString* geometry_shader_code =
generate_geometry_shader(state.polygon_front_mode,
state.polygon_back_mode,
state.primitive_mode,
&gl_primitive_mode);
if (geometry_shader_code) {
const char* geometry_shader_code_str =
qstring_get_str(geometry_shader_code);
mstring_get_str(geometry_shader_code);
GLuint geometry_shader = create_gl_shader(GL_GEOMETRY_SHADER,
geometry_shader_code_str,
"geometry shader");
glAttachShader(program, geometry_shader);
qobject_unref(geometry_shader_code);
mstring_unref(geometry_shader_code);
vtx_prefix = 'v';
} else {
vtx_prefix = 'g';
}
/* create the vertex shader */
QString *vertex_shader_code = generate_vertex_shader(state, vtx_prefix);
MString *vertex_shader_code = generate_vertex_shader(state, vtx_prefix);
GLuint vertex_shader = create_gl_shader(GL_VERTEX_SHADER,
qstring_get_str(vertex_shader_code),
mstring_get_str(vertex_shader_code),
"vertex shader");
glAttachShader(program, vertex_shader);
qobject_unref(vertex_shader_code);
mstring_unref(vertex_shader_code);
/* generate a fragment shader from register combiners */
QString *fragment_shader_code = psh_translate(state.psh);
const char *fragment_shader_code_str = qstring_get_str(fragment_shader_code);
MString *fragment_shader_code = psh_translate(state.psh);
const char *fragment_shader_code_str = mstring_get_str(fragment_shader_code);
GLuint fragment_shader = create_gl_shader(GL_FRAGMENT_SHADER,
fragment_shader_code_str,
"fragment shader");
glAttachShader(program, fragment_shader);
qobject_unref(fragment_shader_code);
mstring_unref(fragment_shader_code);
/* link the program */
glLinkProgram(program);

View File

@ -37,8 +37,80 @@
"};\n"
void qstring_append_fmt(QString *qstring, const char *fmt, ...);
QString *qstring_from_fmt(const char *fmt, ...);
void qstring_append_va(QString *qstring, const char *fmt, va_list va);
typedef struct {
int ref;
gchar *string;
} MString;
void mstring_append_fmt(MString *mstring, const char *fmt, ...);
MString *mstring_from_fmt(const char *fmt, ...);
void mstring_append_va(MString *mstring, const char *fmt, va_list va);
static inline
void mstring_ref(MString *mstr)
{
mstr->ref++;
}
static inline
void mstring_unref(MString *mstr)
{
mstr->ref--;
if (!mstr->ref) {
g_free(mstr->string);
g_free(mstr);
}
}
static inline
void mstring_append(MString *mstr, const char *str)
{
gchar *n = g_strconcat(mstr->string, str, NULL);
g_free(mstr->string);
mstr->string = n;
}
static inline
void mstring_append_chr(MString *mstr, char chr)
{
mstring_append_fmt(mstr, "%c", chr);
}
static inline
void mstring_append_int(MString *mstr, int val)
{
mstring_append_fmt(mstr, "%" PRId64, val);
}
static inline
MString *mstring_new(void)
{
MString *mstr = g_malloc(sizeof(MString));
mstr->ref = 1;
mstr->string = g_strdup("");
return mstr;
}
static inline
MString *mstring_from_str(const char *str)
{
MString *mstr = g_malloc(sizeof(MString));
mstr->ref = 1;
mstr->string = g_strdup(str);
return mstr;
}
static inline
const gchar *mstring_get_str(MString *mstr)
{
return mstr->string;
}
static inline
size_t mstring_get_length(MString *mstr)
{
return strlen(mstr->string);
}
#endif

View File

@ -292,7 +292,7 @@ static int16_t convert_c_register(const int16_t c_reg)
static QString* decode_swizzle(const uint32_t *shader_token,
static MString* decode_swizzle(const uint32_t *shader_token,
VshFieldName swizzle_field)
{
const char* swizzle_str = "xyzw";
@ -312,25 +312,25 @@ static QString* decode_swizzle(const uint32_t *shader_token,
if (x == SWIZZLE_X && y == SWIZZLE_Y
&& z == SWIZZLE_Z && w == SWIZZLE_W) {
/* Don't print the swizzle if it's .xyzw */
return qstring_from_str(""); // Will turn ".xyzw" into "."
return mstring_from_str(""); // Will turn ".xyzw" into "."
/* Don't print duplicates */
} else if (x == y && y == z && z == w) {
return qstring_from_str((char[]){'.', swizzle_str[x], '\0'});
return mstring_from_str((char[]){'.', swizzle_str[x], '\0'});
} else if (y == z && z == w) {
return qstring_from_str((char[]){'.',
return mstring_from_str((char[]){'.',
swizzle_str[x], swizzle_str[y], '\0'});
} else if (z == w) {
return qstring_from_str((char[]){'.',
return mstring_from_str((char[]){'.',
swizzle_str[x], swizzle_str[y], swizzle_str[z], '\0'});
} else {
return qstring_from_str((char[]){'.',
return mstring_from_str((char[]){'.',
swizzle_str[x], swizzle_str[y],
swizzle_str[z], swizzle_str[w],
'\0'}); // Normal swizzle mask
}
}
static QString* decode_opcode_input(const uint32_t *shader_token,
static MString* decode_opcode_input(const uint32_t *shader_token,
VshParameterType param,
VshFieldName neg_field,
int reg_num)
@ -339,11 +339,11 @@ static QString* decode_opcode_input(const uint32_t *shader_token,
* Input A, B or C is controlled via the Param and NEG fieldnames,
* the R-register address for each input is already given by caller. */
QString *ret_str = qstring_new();
MString *ret_str = mstring_new();
if (vsh_get_field(shader_token, neg_field) > 0) {
qstring_append_chr(ret_str, '-');
mstring_append_chr(ret_str, '-');
}
/* PARAM_R uses the supplied reg_num, but the other two need to be
@ -371,26 +371,26 @@ static QString* decode_opcode_input(const uint32_t *shader_token,
assert(false);
break;
}
qstring_append(ret_str, tmp);
mstring_append(ret_str, tmp);
{
/* swizzle bits are next to the neg bit */
QString *swizzle_str = decode_swizzle(shader_token, neg_field+1);
qstring_append(ret_str, qstring_get_str(swizzle_str));
qobject_unref(swizzle_str);
MString *swizzle_str = decode_swizzle(shader_token, neg_field+1);
mstring_append(ret_str, mstring_get_str(swizzle_str));
mstring_unref(swizzle_str);
}
return ret_str;
}
static QString* decode_opcode(const uint32_t *shader_token,
static MString* decode_opcode(const uint32_t *shader_token,
VshOutputMux out_mux,
uint32_t mask,
const char *opcode,
const char *inputs)
{
QString *ret = qstring_new();
MString *ret = mstring_new();
int reg_num = vsh_get_field(shader_token, FLD_OUT_R);
/* Test for paired opcodes (in other words : Are both <> NOP?) */
@ -410,32 +410,32 @@ static QString* decode_opcode(const uint32_t *shader_token,
/* Only if it's not masked away: */
&& vsh_get_field(shader_token, FLD_OUT_O_MASK) != 0) {
qstring_append(ret, " ");
qstring_append(ret, opcode);
qstring_append(ret, "(");
mstring_append(ret, " ");
mstring_append(ret, opcode);
mstring_append(ret, "(");
if (vsh_get_field(shader_token, FLD_OUT_ORB) == OUTPUT_C) {
/* TODO : Emulate writeable const registers */
qstring_append(ret, "c");
qstring_append_int(ret,
mstring_append(ret, "c");
mstring_append_int(ret,
convert_c_register(
vsh_get_field(shader_token, FLD_OUT_ADDRESS)));
} else {
qstring_append(ret,
mstring_append(ret,
out_reg_name[
vsh_get_field(shader_token, FLD_OUT_ADDRESS) & 0xF]);
}
qstring_append(ret,
mstring_append(ret,
mask_str[
vsh_get_field(shader_token, FLD_OUT_O_MASK)]);
qstring_append(ret, inputs);
qstring_append(ret, ");\n");
mstring_append(ret, inputs);
mstring_append(ret, ");\n");
}
if (strcmp(opcode, mac_opcode[MAC_ARL]) == 0) {
qstring_append_fmt(ret, " ARL(A0%s);\n", inputs);
mstring_append_fmt(ret, " ARL(A0%s);\n", inputs);
} else if (mask > 0) {
qstring_append_fmt(ret, " %s(R%d%s%s);\n",
mstring_append_fmt(ret, " %s(R%d%s%s);\n",
opcode, reg_num, mask_str[mask], inputs);
}
@ -443,12 +443,12 @@ static QString* decode_opcode(const uint32_t *shader_token,
}
static QString* decode_token(const uint32_t *shader_token)
static MString* decode_token(const uint32_t *shader_token)
{
QString *ret;
MString *ret;
/* Since it's potentially used twice, decode input C once: */
QString *input_c =
MString *input_c =
decode_opcode_input(shader_token,
vsh_get_field(shader_token, FLD_C_MUX),
FLD_C_NEG,
@ -458,30 +458,30 @@ static QString* decode_token(const uint32_t *shader_token)
/* See what MAC opcode is written to (if not masked away): */
VshMAC mac = vsh_get_field(shader_token, FLD_MAC);
if (mac != MAC_NOP) {
QString *inputs_mac = qstring_new();
MString *inputs_mac = mstring_new();
if (mac_opcode_params[mac].A) {
QString *input_a =
MString *input_a =
decode_opcode_input(shader_token,
vsh_get_field(shader_token, FLD_A_MUX),
FLD_A_NEG,
vsh_get_field(shader_token, FLD_A_R));
qstring_append(inputs_mac, ", ");
qstring_append(inputs_mac, qstring_get_str(input_a));
qobject_unref(input_a);
mstring_append(inputs_mac, ", ");
mstring_append(inputs_mac, mstring_get_str(input_a));
mstring_unref(input_a);
}
if (mac_opcode_params[mac].B) {
QString *input_b =
MString *input_b =
decode_opcode_input(shader_token,
vsh_get_field(shader_token, FLD_B_MUX),
FLD_B_NEG,
vsh_get_field(shader_token, FLD_B_R));
qstring_append(inputs_mac, ", ");
qstring_append(inputs_mac, qstring_get_str(input_b));
qobject_unref(input_b);
mstring_append(inputs_mac, ", ");
mstring_append(inputs_mac, mstring_get_str(input_b));
mstring_unref(input_b);
}
if (mac_opcode_params[mac].C) {
qstring_append(inputs_mac, ", ");
qstring_append(inputs_mac, qstring_get_str(input_c));
mstring_append(inputs_mac, ", ");
mstring_append(inputs_mac, mstring_get_str(input_c));
}
/* Then prepend these inputs with the actual opcode, mask, and input : */
@ -489,33 +489,33 @@ static QString* decode_token(const uint32_t *shader_token)
OMUX_MAC,
vsh_get_field(shader_token, FLD_OUT_MAC_MASK),
mac_opcode[mac],
qstring_get_str(inputs_mac));
qobject_unref(inputs_mac);
mstring_get_str(inputs_mac));
mstring_unref(inputs_mac);
} else {
ret = qstring_new();
ret = mstring_new();
}
/* See if a ILU opcode is present too: */
VshILU ilu = vsh_get_field(shader_token, FLD_ILU);
if (ilu != ILU_NOP) {
QString *inputs_c = qstring_from_str(", ");
qstring_append(inputs_c, qstring_get_str(input_c));
MString *inputs_c = mstring_from_str(", ");
mstring_append(inputs_c, mstring_get_str(input_c));
/* Append the ILU opcode, mask and (the already determined) input C: */
QString *ilu_op =
MString *ilu_op =
decode_opcode(shader_token,
OMUX_ILU,
vsh_get_field(shader_token, FLD_OUT_ILU_MASK),
ilu_opcode[ilu],
qstring_get_str(inputs_c));
mstring_get_str(inputs_c));
qstring_append(ret, qstring_get_str(ilu_op));
mstring_append(ret, mstring_get_str(ilu_op));
qobject_unref(inputs_c);
qobject_unref(ilu_op);
mstring_unref(inputs_c);
mstring_unref(ilu_op);
}
qobject_unref(input_c);
mstring_unref(input_c);
return ret;
}
@ -719,24 +719,24 @@ void vsh_translate(uint16_t version,
const uint32_t *tokens,
unsigned int length,
bool z_perspective,
QString *header, QString *body)
MString *header, MString *body)
{
qstring_append(header, vsh_header);
mstring_append(header, vsh_header);
bool has_final = false;
int slot;
for (slot=0; slot < length; slot++) {
const uint32_t* cur_token = &tokens[slot * VSH_TOKEN_SIZE];
QString *token_str = decode_token(cur_token);
qstring_append_fmt(body,
MString *token_str = decode_token(cur_token);
mstring_append_fmt(body,
" /* Slot %d: 0x%08X 0x%08X 0x%08X 0x%08X */",
slot,
cur_token[0],cur_token[1],cur_token[2],cur_token[3]);
qstring_append(body, "\n");
qstring_append(body, qstring_get_str(token_str));
qstring_append(body, "\n");
qobject_unref(token_str);
mstring_append(body, "\n");
mstring_append(body, mstring_get_str(token_str));
mstring_append(body, "\n");
mstring_unref(token_str);
if (vsh_get_field(cur_token, FLD_FINAL)) {
has_final = true;
@ -748,7 +748,7 @@ void vsh_translate(uint16_t version,
/* pre-divide and output the generated W so we can do persepctive correct
* interpolation manually. OpenGL can't, since we give it a W of 1 to work
* around the perspective divide */
qstring_append(body,
mstring_append(body,
" if (oPos.w == 0.0 || isinf(oPos.w)) {\n"
" vtx.inv_w = 1.0;\n"
" } else {\n"
@ -756,7 +756,7 @@ void vsh_translate(uint16_t version,
" }\n"
);
qstring_append(body,
mstring_append(body,
/* the shaders leave the result in screen space, while
* opengl expects it in clip space.
* TODO: the pixel-center co-ordinate differences should handled
@ -765,9 +765,9 @@ void vsh_translate(uint16_t version,
" oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) / surfaceSize.y;\n"
);
if (z_perspective) {
qstring_append(body, " oPos.z = oPos.w;\n");
mstring_append(body, " oPos.z = oPos.w;\n");
}
qstring_append(body,
mstring_append(body,
/* Map the clip range into clip space so z is clipped correctly.
* Note this makes the values in the depth buffer wrong. This should be
* handled with gl_ClipDistance instead, but that has performance issues

View File

@ -21,7 +21,7 @@
#define HW_NV2A_VSH_H
#include <stdbool.h>
#include "qapi/qmp/qstring.h"
#include "shaders_common.h"
enum VshLight {
LIGHT_OFF,
@ -134,7 +134,7 @@ void vsh_translate(uint16_t version,
const uint32_t *tokens,
unsigned int length,
bool z_perspective,
QString *header, QString *body);
MString *header, MString *body);
#endif