summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/PixelShaderGen.cpp
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2014-03-26 10:05:46 +0100
committerPierre Bourdon <delroth@gmail.com>2014-03-26 10:05:46 +0100
commitea6b37cb750e8cefd60a18a9ed1b5aa0dd4adf8c (patch)
tree8fbae0ac2332479013c61a0cb653c2ba14380ea4 /Source/Core/VideoCommon/PixelShaderGen.cpp
parentc6070b94cec613bb4bd26ae2e1b0835c52b7480c (diff)
parent1dead05cae47aeb9cb9e14a65a286e0f0de8dc95 (diff)
Merge pull request #193 from neobrain/tev_combiner_fixes
PixelShaderGen: Cleanups and fixes for tev combiners.
Diffstat (limited to 'Source/Core/VideoCommon/PixelShaderGen.cpp')
-rw-r--r--Source/Core/VideoCommon/PixelShaderGen.cpp177
1 files changed, 94 insertions, 83 deletions
diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp
index 29399a253f..85d25b2cac 100644
--- a/Source/Core/VideoCommon/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/PixelShaderGen.cpp
@@ -90,27 +90,6 @@ static const char *tevKSelTableA[] =
I_KCOLORS"[3].a", // K3_A = 0x1F
};
-static const char *tevScaleTable[] =
-{
- "", // SCALE_1
- " << 1", // SCALE_2
- " << 2", // SCALE_4
- " >> 1", // DIVIDE_2
-};
-
-static const char *tevBiasTable[] =
-{
- "", // ZERO,
- "+ 128", // ADDHALF,
- "- 128", // SUBHALF,
- "",
-};
-
-static const char *tevOpTable[] = {
- "+", // TEVOP_ADD = 0,
- "-", // TEVOP_SUB = 1,
-};
-
static const char *tevCInputTable[] =
{
"prev.rgb", // CPREV,
@@ -133,14 +112,14 @@ static const char *tevCInputTable[] =
static const char *tevAInputTable[] =
{
- "prev", // APREV,
- "c0", // A0,
- "c1", // A1,
- "c2", // A2,
- "textemp", // TEXA,
- "rastemp", // RASA,
- "konsttemp", // KONST, (hw1 had quarter)
- "int4(0,0,0,0)", // ZERO
+ "prev.a", // APREV,
+ "c0.a", // A0,
+ "c1.a", // A1,
+ "c2.a", // A2,
+ "textemp.a", // TEXA,
+ "rastemp.a", // RASA,
+ "konsttemp.a", // KONST, (hw1 had quarter)
+ "0", // ZERO
};
static const char *tevRasTable[] =
@@ -161,6 +140,7 @@ static const char *tevAOutputTable[] = { "prev.a", "c0.a", "c1.a", "c2.a" };
static char text[16384];
template<class T> static inline void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, API_TYPE ApiType, const char swapModeTable[4][5]);
+template<class T> static inline void WriteTevRegular(T& out, const char* components, int bias, int op, int clamp, int shift);
template<class T> static inline void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
template<class T> static inline void WriteAlphaTest(T& out, pixel_shader_uid_data& uid_data, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth);
template<class T> static inline void WriteFog(T& out, pixel_shader_uid_data& uid_data);
@@ -343,7 +323,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
"\tint3 comp16 = int3(1, 256, 0), comp24 = int3(1, 256, 256*256);\n"
"\tint alphabump=0;\n"
"\tint3 tevcoord=int3(0, 0, 0);\n"
- "\tint2 wrappedcoord=int2(0,0), tempcoord=int2(0,0);\n\n");
+ "\tint2 wrappedcoord=int2(0,0), tempcoord=int2(0,0);\n"
+ "\tint4 tevin_a=int4(0,0,0,0),tevin_b=int4(0,0,0,0),tevin_c=int4(0,0,0,0),tevin_d=int4(0,0,0,0);\n\n"); // tev combiner inputs
if (ApiType == API_OPENGL)
{
@@ -778,44 +759,35 @@ static inline void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, AP
if (ac.dest >= GX_TEVREG0 && ac.dest <= GX_TEVREG2)
out.SetConstantsUsed(C_COLORS+ac.dest, C_COLORS+ac.dest);
+
+ out.Write("tevin_a = int4(%s, %s)&255;\n", tevCInputTable[cc.a], tevAInputTable[ac.a]);
+ out.Write("tevin_b = int4(%s, %s)&255;\n", tevCInputTable[cc.b], tevAInputTable[ac.b]);
+ out.Write("tevin_c = int4(%s, %s)&255;\n", tevCInputTable[cc.c], tevAInputTable[ac.c]);
+ out.Write("tevin_d = int4(%s, %s);\n", tevCInputTable[cc.d], tevAInputTable[ac.d]);
+
out.Write("\t// color combine\n");
out.Write("\t%s = clamp(", tevCOutputTable[cc.dest]);
-
- // combine the color channel
- if (cc.bias != TevBias_COMPARE) // if not compare
+ if (cc.bias != TevBias_COMPARE)
{
- //normal color combiner goes here
- if (cc.shift > TEVSCALE_1)
- out.Write("(");
-
- if (!(cc.d == TEVCOLORARG_ZERO && cc.op == TEVOP_ADD))
- out.Write("%s %s ", tevCInputTable[cc.d], tevOpTable[cc.op]);
-
- out.Write("((%s&255) * (int3(255,255,255) - (%s&255)) + (%s&255) * (%s&255)) / 255", tevCInputTable[cc.a], tevCInputTable[cc.c], tevCInputTable[cc.b], tevCInputTable[cc.c]);
-
- out.Write(" %s", tevBiasTable[cc.bias]);
-
- if (cc.shift > TEVSCALE_1)
- out.Write(")%s", tevScaleTable[cc.shift]);
+ WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.shift);
}
else
{
const char *function_table[] =
{
- "(((%s.r&255) > %s.r) ? (%s&255): int3(0,0,0))", // TEVCMP_R8_GT
- "(((%s.r&255) == %s.r) ? (%s&255): int3(0,0,0))", // TEVCMP_R8_EQ
- "((idot((%s.rgb&255), comp16) > idot((%s.rgb&255), comp16)) ? (%s&255): int3(0,0,0))", // TEVCMP_GR16_GT
- "((idot((%s.rgb&255), comp16) == idot((%s.rgb&255), comp16)) ? (%s&255): int3(0,0,0))", // TEVCMP_GR16_EQ
- "((idot((%s.rgb&255), comp24) > idot((%s.rgb&255), comp24)) ? (%s&255): int3(0,0,0))", // TEVCMP_BGR24_GT
- "((idot((%s.rgb&255), comp24) == idot((%s.rgb&255), comp24)) ? (%s&255): int3(0,0,0))", // TEVCMP_BGR24_EQ
- "int3(max(sign(int3((%s.rgb&255)) - int3((%s.rgb&255))), int3(0,0,0)) * (%s&255))", // TEVCMP_RGB8_GT
- "int3((int3(255,255,255) - max(sign(abs(int3((%s.rgb&255)) - int3((%s.rgb&255)))), int3(0,0,0))) * (%s&255))" // TEVCMP_RGB8_EQ
+ "((tevin_a.r > tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_R8_GT
+ "((tevin_a.r == tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_R8_EQ
+ "((idot(tevin_a.rgb, comp16) > idot(tevin_b.rgb, comp16)) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_GR16_GT
+ "((idot(tevin_a.rgb, comp16) == idot(tevin_b.rgb, comp16)) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_GR16_EQ
+ "((idot(tevin_a.rgb, comp24) > idot(tevin_b.rgb, comp24)) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_BGR24_GT
+ "((idot(tevin_a.rgb, comp24) == idot(tevin_b.rgb, comp24)) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_BGR24_EQ
+ "(max(sign(tevin_a.rgb - tevin_b.rgb), int3(0,0,0)) * tevin_c.rgb)", // TEVCMP_RGB8_GT
+ "((int3(255,255,255) - max(sign(abs(tevin_a.rgb - tevin_b.rgb))), int3(0,0,0))) * tevin_c.rgb)" // TEVCMP_RGB8_EQ
};
int mode = (cc.shift<<1)|cc.op;
- out.Write(" %s + ", tevCInputTable[cc.d]);
- out.Write(function_table[mode], tevCInputTable[cc.a],
- tevCInputTable[cc.b], tevCInputTable[cc.c]);
+ out.Write(" tevin_d.rgb + ");
+ out.Write(function_table[mode]);
}
if (cc.clamp)
out.Write(", int3(0,0,0), int3(255,255,255))");
@@ -825,41 +797,27 @@ static inline void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, AP
out.Write("\t// alpha combine\n");
out.Write("\t%s = clamp(", tevAOutputTable[ac.dest]);
-
- if (ac.bias != TevBias_COMPARE) // if not compare
+ if (ac.bias != TevBias_COMPARE)
{
- //normal alpha combiner goes here
- if (ac.shift > 0)
- out.Write("(");
-
- if (!(ac.d == TEVALPHAARG_ZERO && ac.op == TEVOP_ADD))
- out.Write("%s.a %s ", tevAInputTable[ac.d], tevOpTable[ac.op]);
-
- out.Write("((%s.a&255) * (255 - (%s.a&255)) + (%s.a&255) * (%s.a&255)) / 255", tevAInputTable[ac.a], tevAInputTable[ac.c], tevAInputTable[ac.b], tevAInputTable[ac.c]);
-
- out.Write(" %s",tevBiasTable[ac.bias]);
-
- if (ac.shift>0)
- out.Write(")%s", tevScaleTable[ac.shift]);
+ WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.shift);
}
else
{
const char *function_table[] =
{
- "(((%s.r&255) > (%s.r&255)) ? (%s.a&255) : 0)", // TEVCMP_R8_GT
- "(((%s.r&255) == (%s.r&255)) ? (%s.a&255) : 0)", // TEVCMP_R8_EQ
- "((idot((%s.rgb&255), comp16) > idot((%s.rgb&255), comp16)) ? (%s.a&255) : 0)", // TEVCMP_GR16_GT
- "((idot((%s.rgb&255), comp16) == idot((%s.rgb&255), comp16)) ? (%s.a&255) : 0)", // TEVCMP_GR16_EQ
- "((idot((%s.rgb&255), comp24) > idot((%s.rgb&255), comp24)) ? (%s.a&255) : 0)", // TEVCMP_BGR24_GT
- "((idot((%s.rgb&255), comp24) == idot((%s.rgb&255), comp24)) ? (%s.a&255) : 0)", // TEVCMP_BGR24_EQ
- "(((%s.a&255) > (%s.a&255)) ? (%s.a&255) : 0)", // TEVCMP_A8_GT
- "(((%s.a&255) == (%s.a&255)) ? (%s.a&255) : 0)" // TEVCMP_A8_EQ
+ "((tevin_a.r > tevin_b.r) ? tevin_c.a : 0)", // TEVCMP_R8_GT
+ "((tevin_a.r == tevin_b.r) ? tevin_c.a : 0)", // TEVCMP_R8_EQ
+ "((idot(tevin_a.rgb, comp16) > idot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // TEVCMP_GR16_GT
+ "((idot(tevin_a.rgb, comp16) == idot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // TEVCMP_GR16_EQ
+ "((idot(tevin_a.rgb, comp24) > idot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // TEVCMP_BGR24_GT
+ "((idot(tevin_a.rgb, comp24) == idot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // TEVCMP_BGR24_EQ
+ "((tevin_a.a > tevin_b.a) ? tevin_c.a : 0)", // TEVCMP_A8_GT
+ "((tevin_a.a == tevin_b.a) ? tevin_c.a : 0)" // TEVCMP_A8_EQ
};
int mode = (ac.shift<<1)|ac.op;
- out.Write(" %s.a + ", tevAInputTable[ac.d]);
- out.Write(function_table[mode], tevAInputTable[ac.a],
- tevAInputTable[ac.b], tevAInputTable[ac.c]);
+ out.Write(" tevin_d.a + ");
+ out.Write(function_table[mode]);
}
if (ac.clamp)
out.Write(", 0, 255)");
@@ -870,6 +828,59 @@ static inline void WriteStage(T& out, pixel_shader_uid_data& uid_data, int n, AP
}
template<class T>
+static inline void WriteTevRegular(T& out, const char* components, int bias, int op, int clamp, int shift)
+{
+ const char *tevScaleTableLeft[] =
+ {
+ "", // SCALE_1
+ " << 1", // SCALE_2
+ " << 2", // SCALE_4
+ "", // DIVIDE_2
+ };
+
+ const char *tevScaleTableRight[] =
+ {
+ "", // SCALE_1
+ "", // SCALE_2
+ "", // SCALE_4
+ " >> 1", // DIVIDE_2
+ };
+
+ const char *tevLerpBias[] = // indexed by 2*op+(shift==3)
+ {
+ "",
+ " + 128",
+ "",
+ " + 127",
+ };
+
+ const char *tevBiasTable[] =
+ {
+ "", // ZERO,
+ " + 128", // ADDHALF,
+ " - 128", // SUBHALF,
+ "",
+ };
+
+ const char *tevOpTable[] = {
+ "+", // TEVOP_ADD = 0,
+ "-", // TEVOP_SUB = 1,
+ };
+
+ // Regular TEV stage: (d + bias + lerp(a,b,c)) * scale
+ // The GC/Wii GPU uses a very sophisticated algorithm for scale-lerping:
+ // - c is scaled from 0..255 to 0..256, which allows dividing the result by 256 instead of 255
+ // - if scale is bigger than one, it is moved inside the lerp calculation for increased accuracy
+ // - a rounding bias is added before dividing by 256
+ out.Write("(((tevin_d.%s%s)%s)", components, tevBiasTable[bias], tevScaleTableLeft[shift]);
+ out.Write(" %s ", tevOpTable[op]);
+ out.Write("((((tevin_a.%s*256 + (tevin_b.%s-tevin_a.%s)*(tevin_c.%s+(tevin_c.%s>>7)))%s)%s)>>8)",
+ components, components, components, components, components,
+ tevScaleTableLeft[shift], tevLerpBias[2*op+(shift==3)]);
+ out.Write(")%s", tevScaleTableRight[shift]);
+}
+
+template<class T>
static inline void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType)
{
out.SetConstantsUsed(C_TEXDIMS+texmap,C_TEXDIMS+texmap);