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:
Lioncash 2019-05-29 20:50:17 -04:00
parent e28d08e973
commit 45934dd0c5
1 changed files with 137 additions and 88 deletions

View File

@ -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)