Skip to content

Commit

Permalink
Merge pull request #68 from neobrain/tev_fixes_new
Browse files Browse the repository at this point in the history
Change pixel processing to use integer arithmetic.
  • Loading branch information
neobrain committed Mar 14, 2014
2 parents 450bde2 + 0f81cbd commit a9a8c73
Show file tree
Hide file tree
Showing 12 changed files with 462 additions and 612 deletions.
5 changes: 5 additions & 0 deletions Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,11 +457,15 @@ void ProgramShaderCache::CreateHeader ( void )

// Precision defines for GLSLES3
"%s\n"
"%s\n"

// Silly differences
"#define float2 vec2\n"
"#define float3 vec3\n"
"#define float4 vec4\n"
"#define uint2 uvec2\n"
"#define uint3 uvec3\n"
"#define uint4 uvec4\n"
"#define int2 ivec2\n"
"#define int3 ivec3\n"
"#define int4 ivec4\n"
Expand All @@ -480,6 +484,7 @@ void ProgramShaderCache::CreateHeader ( void )
, g_ActiveConfig.backend_info.bSupportShadingLanguage420pack ? "#extension GL_ARB_shading_language_420pack : enable" : ""

, v==GLSLES3 ? "precision highp float;" : ""
, v==GLSLES3 ? "precision highp int;" : ""

, DriverDetails::HasBug(DriverDetails::BUG_BROKENTEXTURESIZE) ? "#define textureSize(x, y) ivec2(1, 1)" : ""
, DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "#define centroid" : ""
Expand Down
5 changes: 0 additions & 5 deletions Source/Core/VideoBackends/OGL/ProgramShaderCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ class SHADERUID
};


const int NUM_UNIFORMS = 19;
extern const char *UniformNames[NUM_UNIFORMS];

struct SHADER
{
SHADER() : glprogid(0) { }
Expand All @@ -52,8 +49,6 @@ struct SHADER
GLuint glprogid; // opengl program id

std::string strvprog, strpprog;
GLint UniformLocations[NUM_UNIFORMS];
u32 UniformSize[NUM_UNIFORMS];

void SetProgramVariables();
void SetProgramBindings();
Expand Down
26 changes: 14 additions & 12 deletions Source/Core/VideoBackends/Software/Tev.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ void Tev::Indirect(unsigned int stageNum, s32 s, s32 t)
case ITBA_OFF:
AlphaBump = 0;
break;
case ITBA_S:
case ITBA_S:
AlphaBump = indmap[TextureSampler::ALP_SMP];
break;
case ITBA_T:
Expand Down Expand Up @@ -528,9 +528,9 @@ void Tev::Indirect(unsigned int stageNum, s32 s, s32 t)
return;
}

s64 indtevtrans[2] = { 0,0 };
s32 indtevtrans[2] = { 0,0 };

// matrix multiply
// matrix multiply - results might overflow, but we don't care since we only use the lower 24 bits of the result.
int indmtxid = indirect.mid & 3;
if (indmtxid)
{
Expand All @@ -544,19 +544,21 @@ void Tev::Indirect(unsigned int stageNum, s32 s, s32 t)
switch (indirect.mid & 12)
{
case 0:
shift = 3 + (17 - scale);
indtevtrans[0] = indmtx.col0.ma * indcoord[0] + indmtx.col1.mc * indcoord[1] + indmtx.col2.me * indcoord[2];
indtevtrans[1] = indmtx.col0.mb * indcoord[0] + indmtx.col1.md * indcoord[1] + indmtx.col2.mf * indcoord[2];
// matrix values are S0.10, output format is S17.7, so divide by 8
shift = (17 - scale);
indtevtrans[0] = (indmtx.col0.ma * indcoord[0] + indmtx.col1.mc * indcoord[1] + indmtx.col2.me * indcoord[2]) >> 3;
indtevtrans[1] = (indmtx.col0.mb * indcoord[0] + indmtx.col1.md * indcoord[1] + indmtx.col2.mf * indcoord[2]) >> 3;
break;
case 4: // s matrix
shift = 8 + (17 - scale);
indtevtrans[0] = s * indcoord[0];
indtevtrans[1] = t * indcoord[0];
// s is S17.7, matrix elements are divided by 256, output is S17.7, so divide by 256. - TODO: Maybe, since s is actually stored as S24, we should divide by 256*64?
shift = (17 - scale);
indtevtrans[0] = s * indcoord[0] / 256;
indtevtrans[1] = t * indcoord[0] / 256;
break;
case 8: // t matrix
shift = 8 + (17 - scale);
indtevtrans[0] = s * indcoord[1];
indtevtrans[1] = t * indcoord[1];
shift = (17 - scale);
indtevtrans[0] = s * indcoord[1] / 256;
indtevtrans[1] = t * indcoord[1] / 256;
break;
default:
return;
Expand Down
3 changes: 0 additions & 3 deletions Source/Core/VideoCommon/BPMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,9 +411,6 @@ union TEXSCALE
u32 rid : 8;
};
u32 hex;

float getScaleS(int i){return 1.0f/(float)(1<<(i?ss1:ss0));}
float getScaleT(int i){return 1.0f/(float)(1<<(i?ts1:ts0));}
};

union RAS1_IREF
Expand Down
26 changes: 15 additions & 11 deletions Source/Core/VideoCommon/ConstantManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,30 @@ typedef s32 int4[4];

struct PixelShaderConstants
{
float4 colors[4];
float4 kcolors[4];
float4 alpha;
int4 colors[4];
int4 kcolors[4];
int4 alpha;
float4 texdims[8];
float4 zbias[2];
float4 indtexscale[2];
float4 indtexmtx[6];
float4 fog[3];
int4 zbias[2];
int4 indtexscale[2];
int4 indtexmtx[6];
int4 fogcolor;
int4 fogi;
float4 fogf[2];

// For pixel lighting
float4 plights[40];
float4 pmaterials[4];
int4 plight_colors[8];
float4 plights[32];
int4 pmaterials[4];
};

struct VertexShaderConstants
{
float4 posnormalmatrix[6];
float4 projection[4];
float4 materials[4];
float4 lights[40];
int4 materials[4];
int4 light_colors[8]; // 8 lights
float4 lights[32]; // 8 lights * 4 parameters
float4 texmatrices[24];
float4 transformmatrices[64];
float4 normalmatrices[32];
Expand Down
96 changes: 48 additions & 48 deletions Source/Core/VideoCommon/LightingShaderGen.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@
#include "VideoCommon/XFMemory.h"


#define LIGHT_COL "%s[5*%d].%s"
#define LIGHT_COL_PARAMS(lightsName, index, swizzle) (lightsName), (index), (swizzle)
#define LIGHT_COL "%s[%d].%s"
#define LIGHT_COL_PARAMS(lightsColName, index, swizzle) (lightsColName), (index), (swizzle)

#define LIGHT_COSATT "%s[5*%d+1]"
#define LIGHT_COSATT "%s[4*%d]"
#define LIGHT_COSATT_PARAMS(lightsName, index) (lightsName), (index)

#define LIGHT_DISTATT "%s[5*%d+2]"
#define LIGHT_DISTATT "%s[4*%d+1]"
#define LIGHT_DISTATT_PARAMS(lightsName, index) (lightsName), (index)

#define LIGHT_POS "%s[5*%d+3]"
#define LIGHT_POS "%s[4*%d+2]"
#define LIGHT_POS_PARAMS(lightsName, index) (lightsName), (index)

#define LIGHT_DIR "%s[5*%d+4]"
#define LIGHT_DIR "%s[4*%d+3]"
#define LIGHT_DIR_PARAMS(lightsName, index) (lightsName), (index)

/**
Expand All @@ -39,14 +39,11 @@ struct LightingUidData


template<class T>
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index, const char* lightsName, int coloralpha)
static void GenerateLightShader(T& object, LightingUidData& uid_data, int index, int litchan_index, const char* lightsColName, const char* lightsName, int coloralpha)
{
const LitChannel& chan = (litchan_index > 1) ? xfregs.alpha[litchan_index-2] : xfregs.color[litchan_index];
const char* swizzle = "xyzw";
if (coloralpha == 1)
swizzle = "xyz";
else if (coloralpha == 2)
swizzle = "w";
const char* swizzle = (coloralpha == 1) ? "xyz" : (coloralpha == 2) ? "w" : "xyzw";
const char* swizzle_components = (coloralpha == 1) ? "3" : (coloralpha == 2) ? "" : "4";

uid_data.attnfunc |= chan.attnfunc << (2*litchan_index);
uid_data.diffusefunc |= chan.diffusefunc << (2*litchan_index);
Expand All @@ -56,13 +53,14 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
object.Write("lacc.%s += " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(lightsName, index, swizzle));
object.Write("lacc.%s += " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
object.Write("ldir = normalize(" LIGHT_POS".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("lacc.%s += %sdot(ldir, _norm0)) * " LIGHT_COL";\n",
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(", LIGHT_COL_PARAMS(lightsName, index, swizzle));
object.Write("lacc.%s += int%s(round(%sdot(ldir, _norm0)) * float%s(" LIGHT_COL")));\n",
swizzle, swizzle_components, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(",
swizzle_components, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
break;
default: _assert_(0);
}
Expand All @@ -73,35 +71,37 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
{ // spot
object.Write("ldir = " LIGHT_POS".xyz - pos.xyz;\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("dist2 = dot(ldir, ldir);\n"
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
"attn = max(0.0, dot(ldir, " LIGHT_DIR".xyz));\n",
LIGHT_DIR_PARAMS(lightsName, index));
"dist = sqrt(dist2);\n"
"ldir = ldir / dist;\n"
"attn = max(0.0, dot(ldir, " LIGHT_DIR".xyz));\n",
LIGHT_DIR_PARAMS(lightsName, index));
// attn*attn may overflow
object.Write("attn = max(0.0, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / dot(" LIGHT_DISTATT".xyz, float3(1.0,dist,dist2));\n",
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
}
else if (chan.attnfunc == 1)
{ // specular
object.Write("ldir = normalize(" LIGHT_POS".xyz);\n", LIGHT_POS_PARAMS(lightsName, index));
object.Write("attn = (dot(_norm0,ldir) >= 0.0) ? max(0.0, dot(_norm0, " LIGHT_DIR".xyz)) : 0.0;\n", LIGHT_DIR_PARAMS(lightsName, index));
// attn*attn may overflow
object.Write("attn = max(0.0, " LIGHT_COSATT".x + " LIGHT_COSATT".y*attn + " LIGHT_COSATT".z*attn*attn) / (" LIGHT_DISTATT".x + " LIGHT_DISTATT".y*attn + " LIGHT_DISTATT".z*attn*attn);\n",
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index),
LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index), LIGHT_COSATT_PARAMS(lightsName, index),
LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index), LIGHT_DISTATT_PARAMS(lightsName, index));
}

switch (chan.diffusefunc)
{
case LIGHTDIF_NONE:
object.Write("lacc.%s += attn * " LIGHT_COL";\n", swizzle, LIGHT_COL_PARAMS(lightsName, index, swizzle));
object.Write("lacc.%s += int%s(round(attn * float%s(" LIGHT_COL")));\n",
swizzle, swizzle_components,
swizzle_components, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
break;
case LIGHTDIF_SIGN:
case LIGHTDIF_CLAMP:
object.Write("lacc.%s += attn * %sdot(ldir, _norm0)) * " LIGHT_COL";\n",
swizzle,
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0," :"(",
LIGHT_COL_PARAMS(lightsName, index, swizzle));
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_components, LIGHT_COL_PARAMS(lightsColName, index, swizzle));
break;
default: _assert_(0);
}
Expand All @@ -115,7 +115,7 @@ static void GenerateLightShader(T& object, LightingUidData& uid_data, int index,
// inColorName is color in vs and colors_ in ps
// dest is o.colors_ in vs and colors_ in ps
template<class T>
static void GenerateLightingShader(T& object, LightingUidData& uid_data, int components, const char* materialsName, const char* lightsName, const char* inColorName, const char* dest)
static void GenerateLightingShader(T& object, LightingUidData& uid_data, int components, const char* materialsName, const char* lightsColName, const char* lightsName, const char* inColorName, const char* dest)
{
for (unsigned int j = 0; j < xfregs.numChan.numColorChans; j++)
{
Expand All @@ -128,15 +128,15 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
if (color.matsource) // from vertex
{
if (components & (VB_HAS_COL0 << j))
object.Write("mat = %s%d;\n", inColorName, j);
object.Write("int4 mat = int4(round(%s%d * 255.0));\n", inColorName, j);
else if (components & VB_HAS_COL0)
object.Write("mat = %s0;\n", inColorName);
object.Write("int4 mat = int4(round(%s0 * 255.0));\n", inColorName);
else
object.Write("mat = float4(1.0, 1.0, 1.0, 1.0);\n");
object.Write("int4 mat = int4(255, 255, 255, 255);\n");
}
else // from color
{
object.Write("mat = %s[%d];\n", materialsName, j+2);
object.Write("int4 mat = %s[%d];\n", materialsName, j+2);
}

uid_data.enablelighting |= xfregs.color[j].enablelighting << j;
Expand All @@ -146,14 +146,14 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
if (color.ambsource) // from vertex
{
if (components & (VB_HAS_COL0<<j) )
object.Write("lacc = %s%d;\n", inColorName, j);
object.Write("lacc = int4(round(%s%d * 255.0));\n", inColorName, j);
else if (components & VB_HAS_COL0 )
object.Write("lacc = %s0;\n", inColorName);
object.Write("lacc = int4(round(%s0 * 255.0));\n", inColorName);
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
object.Write("lacc = float4(1.0, 1.0, 1.0, 1.0);\n");
object.Write("lacc = int4(255, 255, 255, 255);\n");
}
else // from color
{
Expand All @@ -162,7 +162,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
}
else
{
object.Write("lacc = float4(1.0, 1.0, 1.0, 1.0);\n");
object.Write("lacc = int4(255, 255, 255, 255);\n");
}

// check if alpha is different
Expand All @@ -172,10 +172,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
if (alpha.matsource) // from vertex
{
if (components & (VB_HAS_COL0<<j))
object.Write("mat.w = %s%d.w;\n", inColorName, j);
object.Write("mat.w = int(round(%s%d.w * 255.0));\n", inColorName, j);
else if (components & VB_HAS_COL0)
object.Write("mat.w = %s0.w;\n", inColorName);
else object.Write("mat.w = 1.0;\n");
object.Write("mat.w = int(round(%s0.w * 255.0));\n", inColorName);
else object.Write("mat.w = 255;\n");
}
else // from color
{
Expand All @@ -190,12 +190,12 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
if (alpha.ambsource) // from vertex
{
if (components & (VB_HAS_COL0<<j) )
object.Write("lacc.w = %s%d.w;\n", inColorName, j);
object.Write("lacc.w = int(round(%s%d.w * 255.0));\n", inColorName, j);
else if (components & VB_HAS_COL0 )
object.Write("lacc.w = %s0.w;\n", inColorName);
object.Write("lacc.w = int(round(%s0.w * 255.0));\n", inColorName);
else
// TODO: The same for alpha: We want to read from vertex, but the vertex has no color
object.Write("lacc.w = 1.0;\n");
object.Write("lacc.w = 255;\n");
}
else // from color
{
Expand All @@ -204,7 +204,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
}
else
{
object.Write("lacc.w = 1.0;\n");
object.Write("lacc.w = 255;\n");
}

if (color.enablelighting && alpha.enablelighting)
Expand All @@ -226,7 +226,7 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
{
if (mask & (1<<i))
{
GenerateLightShader<T>(object, uid_data, i, j, lightsName, 3);
GenerateLightShader<T>(object, uid_data, i, j, lightsColName, lightsName, 3);
}
}
}
Expand All @@ -236,9 +236,9 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
for (int i = 0; i < 8; ++i)
{
if (!(mask&(1<<i)) && (color.GetFullLightMask() & (1<<i)))
GenerateLightShader<T>(object, uid_data, i, j, lightsName, 1);
GenerateLightShader<T>(object, uid_data, i, j, lightsColName, lightsName, 1);
if (!(mask&(1<<i)) && (alpha.GetFullLightMask() & (1<<i)))
GenerateLightShader<T>(object, uid_data, i, j+2, lightsName, 2);
GenerateLightShader<T>(object, uid_data, i, j+2, lightsColName, lightsName, 2);
}
}
else if (color.enablelighting || alpha.enablelighting)
Expand All @@ -252,10 +252,10 @@ static void GenerateLightingShader(T& object, LightingUidData& uid_data, int com
for (int i = 0; i < 8; ++i)
{
if (workingchannel.GetFullLightMask() & (1<<i))
GenerateLightShader<T>(object, uid_data, i, lit_index, lightsName, coloralpha);
GenerateLightShader<T>(object, uid_data, i, lit_index, lightsColName, lightsName, coloralpha);
}
}
object.Write("%s%d = mat * clamp(lacc, 0.0, 1.0);\n", dest, j);
object.Write("%s%d = float4(mat * clamp(lacc, 0, 255) / 255) / 255.0;\n", dest, j);
object.Write("}\n");
}
}
Loading

2 comments on commit a9a8c73

@wfowler1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Huh, I see what you guys mean by cleaner code. I've written plenty of crappy code in my day, and it's always satisfying to replace it with something cleaner.

@benjewmin

This comment was marked as off-topic.

Please sign in to comment.