VideoCommon/PixelShaderGen: Make arrays immutable
Many of the arrays defined within this file weren't declared as immutable, which can inhibit the strings being put into the read-only segment. We can declare them constexpr to make them immutable. While we're at it, we can use std::array, to allow bounds conditional bounds checking with standard libraries. The declarations can also be shortened in the future when all platform toolchain versions we use support std::array deduction guides. Currently macOS and FreeBSD builders fail on them.
This commit is contained in:
parent
e28d08e973
commit
45934dd0c5
|
@ -41,7 +41,7 @@ enum : u32
|
||||||
C_PENVCONST_END = C_EFBSCALE + 1
|
C_PENVCONST_END = C_EFBSCALE + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevKSelTableC[] = {
|
constexpr std::array<const char*, 32> tev_ksel_table_c{
|
||||||
"255,255,255", // 1 = 0x00
|
"255,255,255", // 1 = 0x00
|
||||||
"223,223,223", // 7_8 = 0x01
|
"223,223,223", // 7_8 = 0x01
|
||||||
"191,191,191", // 3_4 = 0x02
|
"191,191,191", // 3_4 = 0x02
|
||||||
|
@ -76,7 +76,7 @@ static const char* tevKSelTableC[] = {
|
||||||
I_KCOLORS "[3].aaa", // K3_A = 0x1F
|
I_KCOLORS "[3].aaa", // K3_A = 0x1F
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevKSelTableA[] = {
|
constexpr std::array<const char*, 32> tev_ksel_table_a{
|
||||||
"255", // 1 = 0x00
|
"255", // 1 = 0x00
|
||||||
"223", // 7_8 = 0x01
|
"223", // 7_8 = 0x01
|
||||||
"191", // 3_4 = 0x02
|
"191", // 3_4 = 0x02
|
||||||
|
@ -111,7 +111,7 @@ static const char* tevKSelTableA[] = {
|
||||||
I_KCOLORS "[3].a", // K3_A = 0x1F
|
I_KCOLORS "[3].a", // K3_A = 0x1F
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevCInputTable[] = {
|
constexpr std::array<const char*, 16> tev_c_input_table{
|
||||||
"prev.rgb", // CPREV,
|
"prev.rgb", // CPREV,
|
||||||
"prev.aaa", // APREV,
|
"prev.aaa", // APREV,
|
||||||
"c0.rgb", // C0,
|
"c0.rgb", // C0,
|
||||||
|
@ -130,7 +130,7 @@ static const char* tevCInputTable[] = {
|
||||||
"int3(0,0,0)", // ZERO
|
"int3(0,0,0)", // ZERO
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevAInputTable[] = {
|
constexpr std::array<const char*, 8> tev_a_input_table{
|
||||||
"prev.a", // APREV,
|
"prev.a", // APREV,
|
||||||
"c0.a", // A0,
|
"c0.a", // A0,
|
||||||
"c1.a", // A1,
|
"c1.a", // A1,
|
||||||
|
@ -141,7 +141,7 @@ static const char* tevAInputTable[] = {
|
||||||
"0", // ZERO
|
"0", // ZERO
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevRasTable[] = {
|
constexpr std::array<const char*, 8> tev_ras_table{
|
||||||
"iround(col0 * 255.0)",
|
"iround(col0 * 255.0)",
|
||||||
"iround(col1 * 255.0)",
|
"iround(col1 * 255.0)",
|
||||||
"ERROR13", // 2
|
"ERROR13", // 2
|
||||||
|
@ -152,8 +152,19 @@ static const char* tevRasTable[] = {
|
||||||
"int4(0, 0, 0, 0)", // zero
|
"int4(0, 0, 0, 0)", // zero
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevCOutputTable[] = {"prev.rgb", "c0.rgb", "c1.rgb", "c2.rgb"};
|
constexpr std::array<const char*, 4> tev_c_output_table{
|
||||||
static const char* tevAOutputTable[] = {"prev.a", "c0.a", "c1.a", "c2.a"};
|
"prev.rgb",
|
||||||
|
"c0.rgb",
|
||||||
|
"c1.rgb",
|
||||||
|
"c2.rgb",
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<const char*, 4> tev_a_output_table{
|
||||||
|
"prev.a",
|
||||||
|
"c0.a",
|
||||||
|
"c1.a",
|
||||||
|
"c2.a",
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME: Some of the video card's capabilities (BBox support, EarlyZ support, dstAlpha support)
|
// FIXME: Some of the video card's capabilities (BBox support, EarlyZ support, dstAlpha support)
|
||||||
// leak
|
// leak
|
||||||
|
@ -817,11 +828,11 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const ShaderHostConfig& host
|
||||||
last_ac.hex = uid_data->stagehash[uid_data->genMode_numtevstages].ac;
|
last_ac.hex = uid_data->stagehash[uid_data->genMode_numtevstages].ac;
|
||||||
if (last_cc.dest != 0)
|
if (last_cc.dest != 0)
|
||||||
{
|
{
|
||||||
out.Write("\tprev.rgb = %s;\n", tevCOutputTable[last_cc.dest]);
|
out.Write("\tprev.rgb = %s;\n", tev_c_output_table[last_cc.dest]);
|
||||||
}
|
}
|
||||||
if (last_ac.dest != 0)
|
if (last_ac.dest != 0)
|
||||||
{
|
{
|
||||||
out.Write("\tprev.a = %s;\n", tevAOutputTable[last_ac.dest]);
|
out.Write("\tprev.a = %s;\n", tev_a_output_table[last_ac.dest]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out.Write("\tprev = prev & 255;\n");
|
out.Write("\tprev = prev & 255;\n");
|
||||||
|
@ -953,11 +964,23 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
// coords
|
// coords
|
||||||
if (tevind.bs != ITBA_OFF)
|
if (tevind.bs != ITBA_OFF)
|
||||||
{
|
{
|
||||||
const char* tevIndAlphaSel[] = {"", "x", "y", "z"};
|
constexpr std::array<const char*, 4> tev_ind_alpha_sel{
|
||||||
const char* tevIndAlphaMask[] = {"248", "224", "240",
|
"",
|
||||||
"248"}; // 0b11111000, 0b11100000, 0b11110000, 0b11111000
|
"x",
|
||||||
out.Write("alphabump = iindtex%d.%s & %s;\n", tevind.bt.Value(), tevIndAlphaSel[tevind.bs],
|
"y",
|
||||||
tevIndAlphaMask[tevind.fmt]);
|
"z",
|
||||||
|
};
|
||||||
|
|
||||||
|
// 0b11111000, 0b11100000, 0b11110000, 0b11111000
|
||||||
|
constexpr std::array<const char*, 4> tev_ind_alpha_mask{
|
||||||
|
"248",
|
||||||
|
"224",
|
||||||
|
"240",
|
||||||
|
"248",
|
||||||
|
};
|
||||||
|
|
||||||
|
out.Write("alphabump = iindtex%d.%s & %s;\n", tevind.bt.Value(), tev_ind_alpha_sel[tevind.bs],
|
||||||
|
tev_ind_alpha_mask[tevind.fmt]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -967,31 +990,44 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
if (tevind.mid != 0)
|
if (tevind.mid != 0)
|
||||||
{
|
{
|
||||||
// format
|
// format
|
||||||
const char* tevIndFmtMask[] = {"255", "31", "15", "7"};
|
constexpr std::array<const char*, 4> tev_ind_fmt_mask{
|
||||||
|
"255",
|
||||||
|
"31",
|
||||||
|
"15",
|
||||||
|
"7",
|
||||||
|
};
|
||||||
out.Write("\tint3 iindtevcrd%d = iindtex%d & %s;\n", n, tevind.bt.Value(),
|
out.Write("\tint3 iindtevcrd%d = iindtex%d & %s;\n", n, tevind.bt.Value(),
|
||||||
tevIndFmtMask[tevind.fmt]);
|
tev_ind_fmt_mask[tevind.fmt]);
|
||||||
|
|
||||||
// bias - TODO: Check if this needs to be this complicated...
|
// bias - TODO: Check if this needs to be this complicated...
|
||||||
// indexed by bias
|
// indexed by bias
|
||||||
const char* tevIndBiasField[] = {"", "x", "y", "xy",
|
constexpr std::array<const char*, 8> tev_ind_bias_field{
|
||||||
"z", "xz", "yz", "xyz"};
|
"", "x", "y", "xy", "z", "xz", "yz", "xyz",
|
||||||
|
};
|
||||||
|
|
||||||
// indexed by fmt
|
// indexed by fmt
|
||||||
const char* tevIndBiasAdd[] = {"-128", "1", "1", "1"};
|
constexpr std::array<const char*, 4> tev_ind_bias_add{
|
||||||
|
"-128",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
"1",
|
||||||
|
};
|
||||||
|
|
||||||
if (tevind.bias == ITB_S || tevind.bias == ITB_T || tevind.bias == ITB_U)
|
if (tevind.bias == ITB_S || tevind.bias == ITB_T || tevind.bias == ITB_U)
|
||||||
{
|
{
|
||||||
out.Write("\tiindtevcrd%d.%s += int(%s);\n", n, tevIndBiasField[tevind.bias],
|
out.Write("\tiindtevcrd%d.%s += int(%s);\n", n, tev_ind_bias_field[tevind.bias],
|
||||||
tevIndBiasAdd[tevind.fmt]);
|
tev_ind_bias_add[tevind.fmt]);
|
||||||
}
|
}
|
||||||
else if (tevind.bias == ITB_ST || tevind.bias == ITB_SU || tevind.bias == ITB_TU)
|
else if (tevind.bias == ITB_ST || tevind.bias == ITB_SU || tevind.bias == ITB_TU)
|
||||||
{
|
{
|
||||||
out.Write("\tiindtevcrd%d.%s += int2(%s, %s);\n", n, tevIndBiasField[tevind.bias],
|
out.Write("\tiindtevcrd%d.%s += int2(%s, %s);\n", n, tev_ind_bias_field[tevind.bias],
|
||||||
tevIndBiasAdd[tevind.fmt], tevIndBiasAdd[tevind.fmt]);
|
tev_ind_bias_add[tevind.fmt], tev_ind_bias_add[tevind.fmt]);
|
||||||
}
|
}
|
||||||
else if (tevind.bias == ITB_STU)
|
else if (tevind.bias == ITB_STU)
|
||||||
{
|
{
|
||||||
out.Write("\tiindtevcrd%d.%s += int3(%s, %s, %s);\n", n, tevIndBiasField[tevind.bias],
|
out.Write("\tiindtevcrd%d.%s += int3(%s, %s, %s);\n", n, tev_ind_bias_field[tevind.bias],
|
||||||
tevIndBiasAdd[tevind.fmt], tevIndBiasAdd[tevind.fmt], tevIndBiasAdd[tevind.fmt]);
|
tev_ind_bias_add[tevind.fmt], tev_ind_bias_add[tevind.fmt],
|
||||||
|
tev_ind_bias_add[tevind.fmt]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// multiply by offset matrix and scale - calculations are likely to overflow badly,
|
// multiply by offset matrix and scale - calculations are likely to overflow badly,
|
||||||
|
@ -1078,9 +1114,11 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
// ---------
|
// ---------
|
||||||
// Wrapping
|
// Wrapping
|
||||||
// ---------
|
// ---------
|
||||||
const char* tevIndWrapStart[] = {
|
|
||||||
"0", "(256<<7)", "(128<<7)", "(64<<7)",
|
// TODO: Should the last element be 1 or (1<<7)?
|
||||||
"(32<<7)", "(16<<7)", "1"}; // TODO: Should the last one be 1 or (1<<7)?
|
constexpr std::array<const char*, 7> tev_ind_wrap_start{
|
||||||
|
"0", "(256<<7)", "(128<<7)", "(64<<7)", "(32<<7)", "(16<<7)", "1",
|
||||||
|
};
|
||||||
|
|
||||||
// wrap S
|
// wrap S
|
||||||
if (tevind.sw == ITW_OFF)
|
if (tevind.sw == ITW_OFF)
|
||||||
|
@ -1094,7 +1132,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.Write("\twrappedcoord.x = fixpoint_uv%d.x & (%s - 1);\n", texcoord,
|
out.Write("\twrappedcoord.x = fixpoint_uv%d.x & (%s - 1);\n", texcoord,
|
||||||
tevIndWrapStart[tevind.sw]);
|
tev_ind_wrap_start[tevind.sw]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// wrap T
|
// wrap T
|
||||||
|
@ -1109,7 +1147,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
out.Write("\twrappedcoord.y = fixpoint_uv%d.y & (%s - 1);\n", texcoord,
|
out.Write("\twrappedcoord.y = fixpoint_uv%d.y & (%s - 1);\n", texcoord,
|
||||||
tevIndWrapStart[tevind.tw]);
|
tev_ind_wrap_start[tevind.tw]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tevind.fb_addprev) // add previous tevcoord
|
if (tevind.fb_addprev) // add previous tevcoord
|
||||||
|
@ -1132,17 +1170,27 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
ac.b == TEVALPHAARG_RASA || ac.c == TEVALPHAARG_RASA || ac.d == TEVALPHAARG_RASA)
|
ac.b == TEVALPHAARG_RASA || ac.c == TEVALPHAARG_RASA || ac.d == TEVALPHAARG_RASA)
|
||||||
{
|
{
|
||||||
// Generate swizzle string to represent the Ras color channel swapping
|
// Generate swizzle string to represent the Ras color channel swapping
|
||||||
char rasswap[5] = {"rgba"[stage.tevksel_swap1a], "rgba"[stage.tevksel_swap2a],
|
const char rasswap[5] = {
|
||||||
"rgba"[stage.tevksel_swap1b], "rgba"[stage.tevksel_swap2b], '\0'};
|
"rgba"[stage.tevksel_swap1a],
|
||||||
|
"rgba"[stage.tevksel_swap2a],
|
||||||
|
"rgba"[stage.tevksel_swap1b],
|
||||||
|
"rgba"[stage.tevksel_swap2b],
|
||||||
|
'\0',
|
||||||
|
};
|
||||||
|
|
||||||
out.Write("\trastemp = %s.%s;\n", tevRasTable[stage.tevorders_colorchan], rasswap);
|
out.Write("\trastemp = %s.%s;\n", tev_ras_table[stage.tevorders_colorchan], rasswap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stage.tevorders_enable)
|
if (stage.tevorders_enable)
|
||||||
{
|
{
|
||||||
// Generate swizzle string to represent the texture color channel swapping
|
// Generate swizzle string to represent the texture color channel swapping
|
||||||
char texswap[5] = {"rgba"[stage.tevksel_swap1c], "rgba"[stage.tevksel_swap2c],
|
const char texswap[5] = {
|
||||||
"rgba"[stage.tevksel_swap1d], "rgba"[stage.tevksel_swap2d], '\0'};
|
"rgba"[stage.tevksel_swap1c],
|
||||||
|
"rgba"[stage.tevksel_swap2c],
|
||||||
|
"rgba"[stage.tevksel_swap1d],
|
||||||
|
"rgba"[stage.tevksel_swap2d],
|
||||||
|
'\0',
|
||||||
|
};
|
||||||
|
|
||||||
if (!stage.hasindstage)
|
if (!stage.hasindstage)
|
||||||
{
|
{
|
||||||
|
@ -1164,8 +1212,8 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
cc.d == TEVCOLORARG_KONST || ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST ||
|
cc.d == TEVCOLORARG_KONST || ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST ||
|
||||||
ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST)
|
ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST)
|
||||||
{
|
{
|
||||||
out.Write("\tkonsttemp = int4(%s, %s);\n", tevKSelTableC[stage.tevksel_kc],
|
out.Write("\tkonsttemp = int4(%s, %s);\n", tev_ksel_table_c[stage.tevksel_kc],
|
||||||
tevKSelTableA[stage.tevksel_ka]);
|
tev_ksel_table_a[stage.tevksel_ka]);
|
||||||
|
|
||||||
if (stage.tevksel_kc > 7)
|
if (stage.tevksel_kc > 7)
|
||||||
{
|
{
|
||||||
|
@ -1194,23 +1242,23 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
if (ac.dest >= GX_TEVREG0)
|
if (ac.dest >= GX_TEVREG0)
|
||||||
out.SetConstantsUsed(C_COLORS + ac.dest, C_COLORS + ac.dest);
|
out.SetConstantsUsed(C_COLORS + ac.dest, C_COLORS + ac.dest);
|
||||||
|
|
||||||
out.Write("\ttevin_a = int4(%s, %s)&int4(255, 255, 255, 255);\n", tevCInputTable[cc.a],
|
out.Write("\ttevin_a = int4(%s, %s)&int4(255, 255, 255, 255);\n", tev_c_input_table[cc.a],
|
||||||
tevAInputTable[ac.a]);
|
tev_a_input_table[ac.a]);
|
||||||
out.Write("\ttevin_b = int4(%s, %s)&int4(255, 255, 255, 255);\n", tevCInputTable[cc.b],
|
out.Write("\ttevin_b = int4(%s, %s)&int4(255, 255, 255, 255);\n", tev_c_input_table[cc.b],
|
||||||
tevAInputTable[ac.b]);
|
tev_a_input_table[ac.b]);
|
||||||
out.Write("\ttevin_c = int4(%s, %s)&int4(255, 255, 255, 255);\n", tevCInputTable[cc.c],
|
out.Write("\ttevin_c = int4(%s, %s)&int4(255, 255, 255, 255);\n", tev_c_input_table[cc.c],
|
||||||
tevAInputTable[ac.c]);
|
tev_a_input_table[ac.c]);
|
||||||
out.Write("\ttevin_d = int4(%s, %s);\n", tevCInputTable[cc.d], tevAInputTable[ac.d]);
|
out.Write("\ttevin_d = int4(%s, %s);\n", tev_c_input_table[cc.d], tev_a_input_table[ac.d]);
|
||||||
|
|
||||||
out.Write("\t// color combine\n");
|
out.Write("\t// color combine\n");
|
||||||
out.Write("\t%s = clamp(", tevCOutputTable[cc.dest]);
|
out.Write("\t%s = clamp(", tev_c_output_table[cc.dest]);
|
||||||
if (cc.bias != TEVBIAS_COMPARE)
|
if (cc.bias != TEVBIAS_COMPARE)
|
||||||
{
|
{
|
||||||
WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.shift, false);
|
WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.shift, false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* function_table[] = {
|
constexpr std::array<const char*, 8> function_table{
|
||||||
"((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_GT
|
||||||
"((tevin_a.r == tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_R8_EQ
|
"((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 : "
|
"((idot(tevin_a.rgb, comp16) > idot(tevin_b.rgb, comp16)) ? tevin_c.rgb : "
|
||||||
|
@ -1225,7 +1273,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
"((int3(1,1,1) - sign(abs(tevin_a.rgb - tevin_b.rgb))) * tevin_c.rgb)" // TEVCMP_RGB8_EQ
|
"((int3(1,1,1) - sign(abs(tevin_a.rgb - tevin_b.rgb))) * tevin_c.rgb)" // TEVCMP_RGB8_EQ
|
||||||
};
|
};
|
||||||
|
|
||||||
int mode = (cc.shift << 1) | cc.op;
|
const int mode = (cc.shift << 1) | cc.op;
|
||||||
out.Write(" tevin_d.rgb + ");
|
out.Write(" tevin_d.rgb + ");
|
||||||
out.Write("%s", function_table[mode]);
|
out.Write("%s", function_table[mode]);
|
||||||
}
|
}
|
||||||
|
@ -1236,14 +1284,14 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
out.Write(";\n");
|
out.Write(";\n");
|
||||||
|
|
||||||
out.Write("\t// alpha combine\n");
|
out.Write("\t// alpha combine\n");
|
||||||
out.Write("\t%s = clamp(", tevAOutputTable[ac.dest]);
|
out.Write("\t%s = clamp(", tev_a_output_table[ac.dest]);
|
||||||
if (ac.bias != TEVBIAS_COMPARE)
|
if (ac.bias != TEVBIAS_COMPARE)
|
||||||
{
|
{
|
||||||
WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.shift, true);
|
WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.shift, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const char* function_table[] = {
|
constexpr std::array<const char*, 8> function_table{
|
||||||
"((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_GT
|
||||||
"((tevin_a.r == tevin_b.r) ? tevin_c.a : 0)", // TEVCMP_R8_EQ
|
"((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_GT
|
||||||
|
@ -1254,7 +1302,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
"((tevin_a.a == tevin_b.a) ? tevin_c.a : 0)" // TEVCMP_A8_EQ
|
"((tevin_a.a == tevin_b.a) ? tevin_c.a : 0)" // TEVCMP_A8_EQ
|
||||||
};
|
};
|
||||||
|
|
||||||
int mode = (ac.shift << 1) | ac.op;
|
const int mode = (ac.shift << 1) | ac.op;
|
||||||
out.Write(" tevin_d.a + ");
|
out.Write(" tevin_d.a + ");
|
||||||
out.Write("%s", function_table[mode]);
|
out.Write("%s", function_table[mode]);
|
||||||
}
|
}
|
||||||
|
@ -1269,38 +1317,38 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||||
static void WriteTevRegular(ShaderCode& out, const char* components, int bias, int op, int clamp,
|
static void WriteTevRegular(ShaderCode& out, const char* components, int bias, int op, int clamp,
|
||||||
int shift, bool alpha)
|
int shift, bool alpha)
|
||||||
{
|
{
|
||||||
const char* tevScaleTableLeft[] = {
|
constexpr std::array<const char*, 4> tev_scale_table_left{
|
||||||
"", // SCALE_1
|
"", // SCALE_1
|
||||||
" << 1", // SCALE_2
|
" << 1", // SCALE_2
|
||||||
" << 2", // SCALE_4
|
" << 2", // SCALE_4
|
||||||
"", // DIVIDE_2
|
"", // DIVIDE_2
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* tevScaleTableRight[] = {
|
constexpr std::array<const char*, 4> tev_scale_table_right{
|
||||||
"", // SCALE_1
|
"", // SCALE_1
|
||||||
"", // SCALE_2
|
"", // SCALE_2
|
||||||
"", // SCALE_4
|
"", // SCALE_4
|
||||||
" >> 1", // DIVIDE_2
|
" >> 1", // DIVIDE_2
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* tevLerpBias[] = // indexed by 2*op+(shift==3)
|
// indexed by 2*op+(shift==3)
|
||||||
{
|
constexpr std::array<const char*, 4> tev_lerp_bias{
|
||||||
"",
|
"",
|
||||||
" + 128",
|
" + 128",
|
||||||
"",
|
"",
|
||||||
" + 127",
|
" + 127",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* tevBiasTable[] = {
|
constexpr std::array<const char*, 4> tev_bias_table{
|
||||||
"", // ZERO,
|
"", // ZERO,
|
||||||
" + 128", // ADDHALF,
|
" + 128", // ADDHALF,
|
||||||
" - 128", // SUBHALF,
|
" - 128", // SUBHALF,
|
||||||
"",
|
"",
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* tevOpTable[] = {
|
constexpr std::array<char, 2> tev_op_table{
|
||||||
"+", // TEVOP_ADD = 0,
|
'+', // TEVOP_ADD = 0,
|
||||||
"-", // TEVOP_SUB = 1,
|
'-', // TEVOP_SUB = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Regular TEV stage: (d + bias + lerp(a,b,c)) * scale
|
// Regular TEV stage: (d + bias + lerp(a,b,c)) * scale
|
||||||
|
@ -1308,12 +1356,12 @@ static void WriteTevRegular(ShaderCode& out, const char* components, int bias, i
|
||||||
// - c is scaled from 0..255 to 0..256, which allows dividing the result by 256 instead of 255
|
// - 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
|
// - 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
|
// - a rounding bias is added before dividing by 256
|
||||||
out.Write("(((tevin_d.%s%s)%s)", components, tevBiasTable[bias], tevScaleTableLeft[shift]);
|
out.Write("(((tevin_d.%s%s)%s)", components, tev_bias_table[bias], tev_scale_table_left[shift]);
|
||||||
out.Write(" %s ", tevOpTable[op]);
|
out.Write(" %c ", tev_op_table[op]);
|
||||||
out.Write("(((((tevin_a.%s<<8) + (tevin_b.%s-tevin_a.%s)*(tevin_c.%s+(tevin_c.%s>>7)))%s)%s)>>8)",
|
out.Write("(((((tevin_a.%s<<8) + (tevin_b.%s-tevin_a.%s)*(tevin_c.%s+(tevin_c.%s>>7)))%s)%s)>>8)",
|
||||||
components, components, components, components, components, tevScaleTableLeft[shift],
|
components, components, components, components, components, tev_scale_table_left[shift],
|
||||||
tevLerpBias[2 * op + ((shift == 3) == alpha)]);
|
tev_lerp_bias[2 * op + ((shift == 3) == alpha)]);
|
||||||
out.Write(")%s", tevScaleTableRight[shift]);
|
out.Write(")%s", tev_scale_table_right[shift]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void SampleTexture(ShaderCode& out, const char* texcoords, const char* texswap, int texmap,
|
static void SampleTexture(ShaderCode& out, const char* texcoords, const char* texswap, int texmap,
|
||||||
|
@ -1334,7 +1382,7 @@ static void SampleTexture(ShaderCode& out, const char* texcoords, const char* te
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* tevAlphaFuncsTable[] = {
|
constexpr std::array<const char*, 8> tev_alpha_funcs_table{
|
||||||
"(false)", // NEVER
|
"(false)", // NEVER
|
||||||
"(prev.a < %s)", // LESS
|
"(prev.a < %s)", // LESS
|
||||||
"(prev.a == %s)", // EQUAL
|
"(prev.a == %s)", // EQUAL
|
||||||
|
@ -1345,7 +1393,7 @@ static const char* tevAlphaFuncsTable[] = {
|
||||||
"(true)" // ALWAYS
|
"(true)" // ALWAYS
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char* tevAlphaFunclogicTable[] = {
|
constexpr std::array<const char*, 4> tev_alpha_funclogic_table{
|
||||||
" && ", // and
|
" && ", // and
|
||||||
" || ", // or
|
" || ", // or
|
||||||
" != ", // xor
|
" != ", // xor
|
||||||
|
@ -1355,7 +1403,7 @@ static const char* tevAlphaFunclogicTable[] = {
|
||||||
static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_data, APIType ApiType,
|
static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_data, APIType ApiType,
|
||||||
bool per_pixel_depth, bool use_dual_source)
|
bool per_pixel_depth, bool use_dual_source)
|
||||||
{
|
{
|
||||||
static const char* alphaRef[2] = {I_ALPHA ".r", I_ALPHA ".g"};
|
static constexpr std::array<const char*, 2> alpha_ref{I_ALPHA ".r", I_ALPHA ".g"};
|
||||||
|
|
||||||
out.SetConstantsUsed(C_ALPHA, C_ALPHA);
|
out.SetConstantsUsed(C_ALPHA, C_ALPHA);
|
||||||
|
|
||||||
|
@ -1366,13 +1414,14 @@ static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_dat
|
||||||
|
|
||||||
// Lookup the first component from the alpha function table
|
// Lookup the first component from the alpha function table
|
||||||
int compindex = uid_data->alpha_test_comp0;
|
int compindex = uid_data->alpha_test_comp0;
|
||||||
out.Write(tevAlphaFuncsTable[compindex], alphaRef[0]);
|
out.Write(tev_alpha_funcs_table[compindex], alpha_ref[0]);
|
||||||
|
|
||||||
out.Write("%s", tevAlphaFunclogicTable[uid_data->alpha_test_logic]); // lookup the logic op
|
// Lookup the logic op
|
||||||
|
out.Write("%s", tev_alpha_funclogic_table[uid_data->alpha_test_logic]);
|
||||||
|
|
||||||
// Lookup the second component from the alpha function table
|
// Lookup the second component from the alpha function table
|
||||||
compindex = uid_data->alpha_test_comp1;
|
compindex = uid_data->alpha_test_comp1;
|
||||||
out.Write(tevAlphaFuncsTable[compindex], alphaRef[1]);
|
out.Write(tev_alpha_funcs_table[compindex], alpha_ref[1]);
|
||||||
|
|
||||||
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_NEGATED_BOOLEAN))
|
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_NEGATED_BOOLEAN))
|
||||||
out.Write(") == false) {\n");
|
out.Write(") == false) {\n");
|
||||||
|
@ -1399,7 +1448,7 @@ static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_dat
|
||||||
out.Write("\t}\n");
|
out.Write("\t}\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* tevFogFuncsTable[] = {
|
constexpr std::array<const char*, 8> tev_fog_funcs_table{
|
||||||
"", // No Fog
|
"", // No Fog
|
||||||
"", // ?
|
"", // ?
|
||||||
"", // Linear
|
"", // Linear
|
||||||
|
@ -1456,7 +1505,7 @@ static void WriteFog(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
|
|
||||||
if (uid_data->fog_fsel > 3)
|
if (uid_data->fog_fsel > 3)
|
||||||
{
|
{
|
||||||
out.Write("%s", tevFogFuncsTable[uid_data->fog_fsel]);
|
out.Write("%s", tev_fog_funcs_table[uid_data->fog_fsel]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1509,7 +1558,7 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
{
|
{
|
||||||
if (uid_data->blend_enable)
|
if (uid_data->blend_enable)
|
||||||
{
|
{
|
||||||
static const std::array<const char*, 8> blendSrcFactor{{
|
static constexpr std::array<const char*, 8> blend_src_factor{
|
||||||
"float3(0,0,0);", // ZERO
|
"float3(0,0,0);", // ZERO
|
||||||
"float3(1,1,1);", // ONE
|
"float3(1,1,1);", // ONE
|
||||||
"initial_ocol0.rgb;", // DSTCLR
|
"initial_ocol0.rgb;", // DSTCLR
|
||||||
|
@ -1518,8 +1567,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
"float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
||||||
"initial_ocol0.aaa;", // DSTALPHA
|
"initial_ocol0.aaa;", // DSTALPHA
|
||||||
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
||||||
}};
|
};
|
||||||
static const std::array<const char*, 8> blendSrcFactorAlpha{{
|
static constexpr std::array<const char*, 8> blend_src_factor_alpha{
|
||||||
"0.0;", // ZERO
|
"0.0;", // ZERO
|
||||||
"1.0;", // ONE
|
"1.0;", // ONE
|
||||||
"initial_ocol0.a;", // DSTCLR
|
"initial_ocol0.a;", // DSTCLR
|
||||||
|
@ -1528,8 +1577,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"1.0 - ocol1.a;", // INVSRCALPHA
|
"1.0 - ocol1.a;", // INVSRCALPHA
|
||||||
"initial_ocol0.a;", // DSTALPHA
|
"initial_ocol0.a;", // DSTALPHA
|
||||||
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||||
}};
|
};
|
||||||
static const std::array<const char*, 8> blendDstFactor{{
|
static constexpr std::array<const char*, 8> blend_dst_factor{
|
||||||
"float3(0,0,0);", // ZERO
|
"float3(0,0,0);", // ZERO
|
||||||
"float3(1,1,1);", // ONE
|
"float3(1,1,1);", // ONE
|
||||||
"ocol0.rgb;", // SRCCLR
|
"ocol0.rgb;", // SRCCLR
|
||||||
|
@ -1538,8 +1587,8 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
"float3(1,1,1) - ocol1.aaa;", // INVSRCALPHA
|
||||||
"initial_ocol0.aaa;", // DSTALPHA
|
"initial_ocol0.aaa;", // DSTALPHA
|
||||||
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
"float3(1,1,1) - initial_ocol0.aaa;", // INVDSTALPHA
|
||||||
}};
|
};
|
||||||
static const std::array<const char*, 8> blendDstFactorAlpha{{
|
static constexpr std::array<const char*, 8> blend_dst_factor_alpha{
|
||||||
"0.0;", // ZERO
|
"0.0;", // ZERO
|
||||||
"1.0;", // ONE
|
"1.0;", // ONE
|
||||||
"ocol0.a;", // SRCCLR
|
"ocol0.a;", // SRCCLR
|
||||||
|
@ -1548,13 +1597,13 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||||
"1.0 - ocol1.a;", // INVSRCALPHA
|
"1.0 - ocol1.a;", // INVSRCALPHA
|
||||||
"initial_ocol0.a;", // DSTALPHA
|
"initial_ocol0.a;", // DSTALPHA
|
||||||
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||||
}};
|
};
|
||||||
out.Write("\tfloat4 blend_src;\n");
|
out.Write("\tfloat4 blend_src;\n");
|
||||||
out.Write("\tblend_src.rgb = %s\n", blendSrcFactor[uid_data->blend_src_factor]);
|
out.Write("\tblend_src.rgb = %s\n", blend_src_factor[uid_data->blend_src_factor]);
|
||||||
out.Write("\tblend_src.a = %s\n", blendSrcFactorAlpha[uid_data->blend_src_factor_alpha]);
|
out.Write("\tblend_src.a = %s\n", blend_src_factor_alpha[uid_data->blend_src_factor_alpha]);
|
||||||
out.Write("\tfloat4 blend_dst;\n");
|
out.Write("\tfloat4 blend_dst;\n");
|
||||||
out.Write("\tblend_dst.rgb = %s\n", blendDstFactor[uid_data->blend_dst_factor]);
|
out.Write("\tblend_dst.rgb = %s\n", blend_dst_factor[uid_data->blend_dst_factor]);
|
||||||
out.Write("\tblend_dst.a = %s\n", blendDstFactorAlpha[uid_data->blend_dst_factor_alpha]);
|
out.Write("\tblend_dst.a = %s\n", blend_dst_factor_alpha[uid_data->blend_dst_factor_alpha]);
|
||||||
|
|
||||||
out.Write("\tfloat4 blend_result;\n");
|
out.Write("\tfloat4 blend_result;\n");
|
||||||
if (uid_data->blend_subtract)
|
if (uid_data->blend_subtract)
|
||||||
|
|
Loading…
Reference in New Issue