mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-24 14:49:42 -06:00
Multithreadded Shadergen: First Pass over vertex/lighting Shadergens
The only code which touches xfmem is code which writes directly into uid_data. All the rest now read their parameters out of uid_data. I also simplified the lighting code so it always generated seperate codepaths for alpha and color channels instead of trying to combine them on the off-chance that the same equation works for all 4 channels. As modern (post 2008) GPUs generally don't calcualte all 4 channels in a single vector, this optimisation is pointless. The shader compiler will undo it during the GLSL/HLSL to IR step. Bug Fix: The about optimisation was also broken, applying the color light equation to the alpha light channel instead of the alpha light euqation. But doesn't look like anything trigged this bug.
This commit is contained in:
@ -48,17 +48,15 @@ static const char s_lighting_struct[] = "struct Light {\n"
|
||||
|
||||
template <class T>
|
||||
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index,
|
||||
int coloralpha)
|
||||
bool alpha)
|
||||
{
|
||||
const LitChannel& chan =
|
||||
(litchan_index > 1) ? xfmem.alpha[litchan_index - 2] : xfmem.color[litchan_index];
|
||||
const char* swizzle = (coloralpha == 1) ? "xyz" : (coloralpha == 2) ? "w" : "xyzw";
|
||||
const char* swizzle_components = (coloralpha == 1) ? "3" : (coloralpha == 2) ? "" : "4";
|
||||
const char* swizzle = alpha ? "a" : "rgb";
|
||||
const char* swizzle_components = (alpha) ? "" : "3";
|
||||
|
||||
uid_data.attnfunc |= chan.attnfunc << (2 * litchan_index);
|
||||
uid_data.diffusefunc |= chan.diffusefunc << (2 * litchan_index);
|
||||
int attnfunc = (uid_data.attnfunc >> (2 * litchan_index)) & 0x3;
|
||||
int diffusefunc = (uid_data.diffusefunc >> (2 * litchan_index)) & 0x3;
|
||||
|
||||
switch (chan.attnfunc)
|
||||
switch (attnfunc)
|
||||
{
|
||||
case LIGHTATTN_NONE:
|
||||
case LIGHTATTN_DIR:
|
||||
@ -73,8 +71,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
LIGHT_DIR_PARAMS(index));
|
||||
object.Write("cosAttn = " LIGHT_COSATT ".xyz;\n", LIGHT_COSATT_PARAMS(index));
|
||||
object.Write("distAttn = %s(" LIGHT_DISTATT ".xyz);\n",
|
||||
(chan.diffusefunc == LIGHTDIF_NONE) ? "" : "normalize",
|
||||
LIGHT_DISTATT_PARAMS(index));
|
||||
(diffusefunc == LIGHTDIF_NONE) ? "" : "normalize", LIGHT_DISTATT_PARAMS(index));
|
||||
object.Write("attn = max(0.0f, dot(cosAttn, float3(1.0, attn, attn*attn))) / dot(distAttn, "
|
||||
"float3(1.0, attn, attn*attn));\n");
|
||||
break;
|
||||
@ -91,11 +88,9 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index), LIGHT_COSATT_PARAMS(index),
|
||||
LIGHT_DISTATT_PARAMS(index));
|
||||
break;
|
||||
default:
|
||||
_assert_(0);
|
||||
}
|
||||
|
||||
switch (chan.diffusefunc)
|
||||
switch (diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
object.Write("lacc.%s += int%s(round(attn * float%s(" LIGHT_COL ")));\n", swizzle,
|
||||
@ -104,7 +99,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
|
||||
case LIGHTDIF_SIGN:
|
||||
case LIGHTDIF_CLAMP:
|
||||
object.Write("lacc.%s += int%s(round(attn * %sdot(ldir, _norm0)) * float%s(" LIGHT_COL ")));\n",
|
||||
swizzle, swizzle_components, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," : "(",
|
||||
swizzle, swizzle_components, diffusefunc != LIGHTDIF_SIGN ? "max(0.0," : "(",
|
||||
swizzle_components, LIGHT_COL_PARAMS(index, swizzle));
|
||||
break;
|
||||
default:
|
||||
@ -131,7 +126,8 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
object.Write("{\n");
|
||||
|
||||
uid_data.matsource |= xfmem.color[j].matsource << j;
|
||||
if (color.matsource) // from vertex
|
||||
bool colormatsource = !!(uid_data.matsource & (1 << j));
|
||||
if (colormatsource) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("int4 mat = int4(round(%s%d * 255.0));\n", inColorName, j);
|
||||
@ -146,10 +142,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
}
|
||||
|
||||
uid_data.enablelighting |= xfmem.color[j].enablelighting << j;
|
||||
if (color.enablelighting)
|
||||
if (uid_data.enablelighting & (1 << j))
|
||||
{
|
||||
uid_data.ambsource |= xfmem.color[j].ambsource << j;
|
||||
if (color.ambsource) // from vertex
|
||||
if (uid_data.ambsource & (1 << j)) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("lacc = int4(round(%s%d * 255.0));\n", inColorName, j);
|
||||
@ -158,7 +154,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
else
|
||||
// TODO: this isn't verified. Here we want to read the ambient from the vertex,
|
||||
// but the vertex itself has no color. So we don't know which value to read.
|
||||
// Returing 1.0 is the same as disabled lightning, so this could be fine
|
||||
// Returning 1.0 is the same as disabled lightning, so this could be fine
|
||||
object.Write("lacc = int4(255, 255, 255, 255);\n");
|
||||
}
|
||||
else // from color
|
||||
@ -173,9 +169,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
|
||||
// check if alpha is different
|
||||
uid_data.matsource |= xfmem.alpha[j].matsource << (j + 2);
|
||||
if (alpha.matsource != color.matsource)
|
||||
bool alphamatsource = !!(uid_data.matsource & (1 << (j + 2)));
|
||||
if (alphamatsource != colormatsource)
|
||||
{
|
||||
if (alpha.matsource) // from vertex
|
||||
if (alphamatsource) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("mat.w = int(round(%s%d.w * 255.0));\n", inColorName, j);
|
||||
@ -191,10 +188,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
}
|
||||
|
||||
uid_data.enablelighting |= xfmem.alpha[j].enablelighting << (j + 2);
|
||||
if (alpha.enablelighting)
|
||||
if (uid_data.enablelighting & (1 << (j + 2)))
|
||||
{
|
||||
uid_data.ambsource |= xfmem.alpha[j].ambsource << (j + 2);
|
||||
if (alpha.ambsource) // from vertex
|
||||
if (uid_data.ambsource & (1 << (j + 2))) // from vertex
|
||||
{
|
||||
if (components & (VB_HAS_COL0 << j))
|
||||
object.Write("lacc.w = int(round(%s%d.w * 255.0));\n", inColorName, j);
|
||||
@ -214,53 +211,23 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
|
||||
object.Write("lacc.w = 255;\n");
|
||||
}
|
||||
|
||||
if (color.enablelighting && alpha.enablelighting)
|
||||
if (uid_data.enablelighting & (1 << j)) // Color lights
|
||||
{
|
||||
// both have lighting, test if they use the same lights
|
||||
int mask = 0;
|
||||
uid_data.attnfunc |= color.attnfunc << (2 * j);
|
||||
uid_data.attnfunc |= alpha.attnfunc << (2 * (j + 2));
|
||||
uid_data.diffusefunc |= color.diffusefunc << (2 * j);
|
||||
uid_data.diffusefunc |= alpha.diffusefunc << (2 * (j + 2));
|
||||
uid_data.light_mask |= color.GetFullLightMask() << (8 * j);
|
||||
uid_data.light_mask |= alpha.GetFullLightMask() << (8 * (j + 2));
|
||||
if (color.lightparams == alpha.lightparams)
|
||||
{
|
||||
mask = color.GetFullLightMask() & alpha.GetFullLightMask();
|
||||
if (mask)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (mask & (1 << i))
|
||||
{
|
||||
GenerateLightShader<T>(object, uid_data, i, j, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// no shared lights
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (!(mask & (1 << i)) && (color.GetFullLightMask() & (1 << i)))
|
||||
GenerateLightShader<T>(object, uid_data, i, j, 1);
|
||||
if (!(mask & (1 << i)) && (alpha.GetFullLightMask() & (1 << i)))
|
||||
GenerateLightShader<T>(object, uid_data, i, j + 2, 2);
|
||||
}
|
||||
if (uid_data.light_mask & (1 << (i + 8 * j)))
|
||||
GenerateLightShader<T>(object, uid_data, i, j, false);
|
||||
}
|
||||
else if (color.enablelighting || alpha.enablelighting)
|
||||
if (uid_data.enablelighting & (1 << (j + 2))) // Alpha lights
|
||||
{
|
||||
// lights are disabled on one channel so process only the active ones
|
||||
const LitChannel& workingchannel = color.enablelighting ? color : alpha;
|
||||
const int lit_index = color.enablelighting ? j : (j + 2);
|
||||
int coloralpha = color.enablelighting ? 1 : 2;
|
||||
|
||||
uid_data.light_mask |= workingchannel.GetFullLightMask() << (8 * lit_index);
|
||||
uid_data.attnfunc |= alpha.attnfunc << (2 * (j + 2));
|
||||
uid_data.diffusefunc |= alpha.diffusefunc << (2 * (j + 2));
|
||||
uid_data.light_mask |= alpha.GetFullLightMask() << (8 * (j + 2));
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (workingchannel.GetFullLightMask() & (1 << i))
|
||||
GenerateLightShader<T>(object, uid_data, i, lit_index, coloralpha);
|
||||
}
|
||||
if (uid_data.light_mask & (1 << (i + 8 * (j + 2))))
|
||||
GenerateLightShader<T>(object, uid_data, i, j + 2, true);
|
||||
}
|
||||
object.Write("lacc = clamp(lacc, 0, 255);\n");
|
||||
object.Write("%s%d = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n", dest, j);
|
||||
|
Reference in New Issue
Block a user