Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge branch 'shader-uids-awesome'.
Replaces the old, hardcoded shader ID generator with a semi-automatic mechanism that generates IDs from hints in the code generator.

Also introduces a flexible framework to do all kinds of funky stuff with the shader code generation logic. As an example, a uniform usage profile generation class is added (unused for now, though).

Functionality can still be tested by setting the EnableShaderDebugging field in the gfx config to True. Any two shaders which are identified with the same ID will be written to a file and an error message will be written to the Dolphin log.
  • Loading branch information
neobrain committed Jun 17, 2013
2 parents 868c627 + 8816369 commit 88bc825
Show file tree
Hide file tree
Showing 28 changed files with 1,625 additions and 1,396 deletions.
7 changes: 6 additions & 1 deletion Source/Core/VideoCommon/Src/BPMemory.h
Expand Up @@ -144,6 +144,11 @@
#define TEVALPHAARG_KONST 6
#define TEVALPHAARG_ZERO 7

#define GX_TEVPREV 0
#define GX_TEVREG0 1
#define GX_TEVREG1 2
#define GX_TEVREG2 3

#define ALPHACMP_NEVER 0
#define ALPHACMP_LESS 1
#define ALPHACMP_EQUAL 2
Expand Down Expand Up @@ -371,7 +376,7 @@ struct TevStageCombiner

union TwoTevStageOrders
{
struct
struct
{
u32 texmap0 : 3; // indirect tex stage texmap
u32 texcoord0 : 3;
Expand Down
10 changes: 5 additions & 5 deletions Source/Core/VideoCommon/Src/Debugger.cpp
Expand Up @@ -89,21 +89,21 @@ void GFXDebuggerBase::DumpPixelShader(const char* path)
if (!useDstAlpha)
{
output = "Destination alpha disabled:\n";
output += GeneratePixelShaderCode(DSTALPHA_NONE, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
/// output += GeneratePixelShaderCode(DSTALPHA_NONE, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
}
else
{
if(g_ActiveConfig.backend_info.bSupportsDualSourceBlend)
{
output = "Using dual source blending for destination alpha:\n";
output += GeneratePixelShaderCode(DSTALPHA_DUAL_SOURCE_BLEND, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
/// output += GeneratePixelShaderCode(DSTALPHA_DUAL_SOURCE_BLEND, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
}
else
{
output = "Using two passes for emulating destination alpha:\n";
output += GeneratePixelShaderCode(DSTALPHA_NONE, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
/// output += GeneratePixelShaderCode(DSTALPHA_NONE, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
output += "\n\nDestination alpha pass shader:\n";
output += GeneratePixelShaderCode(DSTALPHA_ALPHA_PASS, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
/// output += GeneratePixelShaderCode(DSTALPHA_ALPHA_PASS, g_ActiveConfig.backend_info.APIType, g_nativeVertexFmt->m_components);
}
}

Expand All @@ -117,7 +117,7 @@ void GFXDebuggerBase::DumpVertexShader(const char* path)
sprintf(filename, "%sdump_vs.txt", path);

File::CreateEmptyFile(filename);
File::WriteStringToFile(true, GenerateVertexShaderCode(g_nativeVertexFmt->m_components, g_ActiveConfig.backend_info.APIType), filename);
/// File::WriteStringToFile(true, GenerateVertexShaderCode(g_nativeVertexFmt->m_components, g_ActiveConfig.backend_info.APIType), filename);
}

void GFXDebuggerBase::DumpPixelShaderConstants(const char* path)
Expand Down
214 changes: 0 additions & 214 deletions Source/Core/VideoCommon/Src/LightingShaderGen.cpp
Expand Up @@ -5,217 +5,3 @@
#include "LightingShaderGen.h"
#include "NativeVertexFormat.h"
#include "XFMemory.h"

#define WRITE p+=sprintf

int GetLightingShaderId(u32* out)
{
for (u32 i = 0; i < xfregs.numChan.numColorChans; ++i)
{
out[i] = xfregs.color[i].enablelighting ?
(u32)xfregs.color[i].hex :
(u32)xfregs.color[i].matsource;
out[i] |= (xfregs.alpha[i].enablelighting ?
(u32)xfregs.alpha[i].hex :
(u32)xfregs.alpha[i].matsource) << 15;
}
_assert_(xfregs.numChan.numColorChans <= 2);
return xfregs.numChan.numColorChans;
}

// coloralpha - 1 if color, 2 if alpha
char *GenerateLightShader(char *p, int index, const LitChannel& chan, const char* lightsName, int coloralpha)
{
const char* swizzle = "xyzw";

if (coloralpha == 1 )
swizzle = "xyz";
else if (coloralpha == 2 )
swizzle = "w";

if (!(chan.attnfunc & 1))
{
// attenuation disabled
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
WRITE(p, "lacc.%s += %s[%d].%s;\n", swizzle, lightsName, index * 5, swizzle);
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
WRITE(p, "ldir = normalize(%s[%d + 3].xyz - pos.xyz);\n", lightsName, index * 5);
WRITE(p, "lacc.%s += %sdot(ldir, _norm0)) * %s[%d].%s;\n",
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", lightsName, index * 5, swizzle);
break;
default: _assert_(0);
}
}
else // spec and spot
{
if (chan.attnfunc == 3)
{ // spot
WRITE(p, "ldir = %s[%d + 3].xyz - pos.xyz;\n", lightsName, index * 5);
WRITE(p, "dist2 = dot(ldir, ldir);\n"
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
"attn = max(0.0f, dot(ldir, %s[%d + 4].xyz));\n", lightsName, index * 5);
WRITE(p, "attn = max(0.0f, dot(%s[%d + 1].xyz, float3(1.0f, attn, attn*attn))) / dot(%s[%d + 2].xyz, float3(1.0f,dist,dist2));\n", lightsName, index * 5, lightsName, index * 5);
}
else if (chan.attnfunc == 1)
{ // specular
WRITE(p, "ldir = normalize(%s[%d + 3].xyz);\n", lightsName, index * 5);
WRITE(p, "attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s[%d + 4].xyz)) : 0.0f;\n", lightsName, index * 5);
WRITE(p, "attn = max(0.0f, dot(%s[%d + 1].xyz, float3(1,attn,attn*attn))) / dot(%s[%d + 2].xyz, float3(1,attn,attn*attn));\n", lightsName, index * 5, lightsName, index * 5);
}

switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
WRITE(p, "lacc.%s += attn * %s[%d].%s;\n", swizzle, lightsName, index * 5, swizzle);
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
WRITE(p, "lacc.%s += attn * %sdot(ldir, _norm0)) * %s[%d].%s;\n",
swizzle,
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(",
lightsName,
index * 5,
swizzle);
break;
default: _assert_(0);
}
}
WRITE(p, "\n");
return p;
}

// vertex shader
// lights/colors
// materials name is I_MATERIALS in vs and I_PMATERIALS in ps
// inColorName is color in vs and colors_ in ps
// dest is o.colors_ in vs and colors_ in ps
char *GenerateLightingShader(char *p, int components, const char* materialsName, const char* lightsName, const char* inColorName, const char* dest)
{
for (unsigned int j = 0; j < xfregs.numChan.numColorChans; j++)
{
const LitChannel& color = xfregs.color[j];
const LitChannel& alpha = xfregs.alpha[j];

WRITE(p, "{\n");

if (color.matsource) // from vertex
{
if (components & (VB_HAS_COL0 << j))
WRITE(p, "mat = %s%d;\n", inColorName, j);
else if (components & VB_HAS_COL0)
WRITE(p, "mat = %s0;\n", inColorName);
else
WRITE(p, "mat = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
}
else // from color
{
WRITE(p, "mat = %s[%d];\n", materialsName, j+2);
}

if (color.enablelighting)
{
if (color.ambsource) // from vertex
{
if (components & (VB_HAS_COL0<<j) )
WRITE(p, "lacc = %s%d;\n", inColorName, j);
else if (components & VB_HAS_COL0 )
WRITE(p, "lacc = %s0;\n", inColorName);
else
WRITE(p, "lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
}
else // from color
{
WRITE(p, "lacc = %s[%d];\n", materialsName, j);
}
}
else
{
WRITE(p, "lacc = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
}

// check if alpha is different
if (alpha.matsource != color.matsource)
{
if (alpha.matsource) // from vertex
{
if (components & (VB_HAS_COL0<<j))
WRITE(p, "mat.w = %s%d.w;\n", inColorName, j);
else if (components & VB_HAS_COL0)
WRITE(p, "mat.w = %s0.w;\n", inColorName);
else WRITE(p, "mat.w = 1.0f;\n");
}
else // from color
{
WRITE(p, "mat.w = %s[%d].w;\n", materialsName, j+2);
}
}

if (alpha.enablelighting)
{
if (alpha.ambsource) // from vertex
{
if (components & (VB_HAS_COL0<<j) )
WRITE(p, "lacc.w = %s%d.w;\n", inColorName, j);
else if (components & VB_HAS_COL0 )
WRITE(p, "lacc.w = %s0.w;\n", inColorName);
else
WRITE(p, "lacc.w = 0.0f;\n");
}
else // from color
{
WRITE(p, "lacc.w = %s[%d].w;\n", materialsName, j);
}
}
else
{
WRITE(p, "lacc.w = 1.0f;\n");
}

if(color.enablelighting && alpha.enablelighting)
{
// both have lighting, test if they use the same lights
int mask = 0;
if(color.lightparams == alpha.lightparams)
{
mask = color.GetFullLightMask() & alpha.GetFullLightMask();
if(mask)
{
for (int i = 0; i < 8; ++i)
{
if (mask & (1<<i))
p = GenerateLightShader(p, i, color, lightsName, 3);
}
}
}

// no shared lights
for (int i = 0; i < 8; ++i)
{
if (!(mask&(1<<i)) && (color.GetFullLightMask() & (1<<i)))
p = GenerateLightShader(p, i, color, lightsName, 1);
if (!(mask&(1<<i)) && (alpha.GetFullLightMask() & (1<<i)))
p = GenerateLightShader(p, i, alpha, lightsName, 2);
}
}
else if (color.enablelighting || alpha.enablelighting)
{
// lights are disabled on one channel so process only the active ones
const LitChannel& workingchannel = color.enablelighting ? color : alpha;
int coloralpha = color.enablelighting ? 1 : 2;
for (int i = 0; i < 8; ++i)
{
if (workingchannel.GetFullLightMask() & (1<<i))
p = GenerateLightShader(p, i, workingchannel, lightsName, coloralpha);
}
}
WRITE(p, "%s%d = mat * clamp(lacc, 0.0, 1.0);\n", dest, j);
WRITE(p, "}\n");
}

return p;
}

0 comments on commit 88bc825

Please sign in to comment.