diff options
Diffstat (limited to 'Source/Core/VideoCommon/PixelShaderGen.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/PixelShaderGen.cpp | 213 |
1 files changed, 68 insertions, 145 deletions
diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index ad251203f9..2a65a32836 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -6,6 +6,7 @@ #include <cmath> #include <cstdio> +#include "Common/Common.h" #include "VideoCommon/BoundingBox.h" #include "VideoCommon/BPMemory.h" #include "VideoCommon/ConstantManager.h" @@ -17,6 +18,24 @@ #include "VideoCommon/VideoConfig.h" #include "VideoCommon/XFMemory.h" // for texture projection mode +// TODO: Get rid of these +enum : u32 +{ + C_COLORMATRIX = 0, // 0 + C_COLORS = 0, // 0 + C_KCOLORS = C_COLORS + 4, // 4 + C_ALPHA = C_KCOLORS + 4, // 8 + C_TEXDIMS = C_ALPHA + 1, // 9 + C_ZBIAS = C_TEXDIMS + 8, // 17 + C_INDTEXSCALE = C_ZBIAS + 2, // 19 + C_INDTEXMTX = C_INDTEXSCALE + 2, // 21 + C_FOGCOLOR = C_INDTEXMTX + 6, // 27 + C_FOGI = C_FOGCOLOR + 1, // 28 + C_FOGF = C_FOGI + 1, // 29 + C_ZSLOPE = C_FOGF + 2, // 31 + C_EFBSCALE = C_ZSLOPE + 1, // 32 + C_PENVCONST_END = C_EFBSCALE + 1 +}; static const char *tevKSelTableC[] = { @@ -137,7 +156,7 @@ static const char *tevRasTable[] = static const char *tevCOutputTable[] = { "prev.rgb", "c0.rgb", "c1.rgb", "c2.rgb" }; static const char *tevAOutputTable[] = { "prev.a", "c0.a", "c1.a", "c2.a" }; -static char text[16384]; +static char text[32768]; template<class T> static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, API_TYPE ApiType, const char swapModeTable[4][5]); template<class T> static inline void WriteTevRegular(T& out, const char* components, int bias, int op, int clamp, int shift); @@ -196,30 +215,6 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T "int3 itrunc(float3 x) { return int3(trunc(x)); }\n" "int4 itrunc(float4 x) { return int4(trunc(x)); }\n\n"); - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - { - // Add functions to do shifts on scalars and ivecs. - // These functions all have the same name to enable them to be used no matter what code is generated. - // For example: tev color op code uses .rgb as a swizzle, but alpha code only uses .a. - out.Write("int ilshift(int a, int b) { return a << b; }\n" - "int irshift(int a, int b) { return a >> b; }\n" - - "int2 ilshift(int2 a, int2 b) { return int2(a.x << b.x, a.y << b.y); }\n" - "int2 ilshift(int2 a, int b) { return int2(a.x << b, a.y << b); }\n" - "int2 irshift(int2 a, int2 b) { return int2(a.x >> b.x, a.y >> b.y); }\n" - "int2 irshift(int2 a, int b) { return int2(a.x >> b, a.y >> b); }\n" - - "int3 ilshift(int3 a, int3 b) { return int3(a.x << b.x, a.y << b.y, a.z << b.z); }\n" - "int3 ilshift(int3 a, int b) { return int3(a.x << b, a.y << b, a.z << b); }\n" - "int3 irshift(int3 a, int3 b) { return int3(a.x >> b.x, a.y >> b.y, a.z >> b.z); }\n" - "int3 irshift(int3 a, int b) { return int3(a.x >> b, a.y >> b, a.z >> b); }\n" - - "int4 ilshift(int4 a, int4 b) { return int4(a.x << b.x, a.y << b.y, a.z << b.z, a.w << b.w); }\n" - "int4 ilshift(int4 a, int b) { return int4(a.x << b, a.y << b, a.z << b, a.w << b); }\n" - "int4 irshift(int4 a, int4 b) { return int4(a.x >> b.x, a.y >> b.y, a.z >> b.z, a.w >> b.w); }\n" - "int4 irshift(int4 a, int b) { return int4(a.x >> b, a.y >> b, a.z >> b, a.w >> b); }\n\n"); - } - if (ApiType == API_OPENGL) { // Declare samplers @@ -338,6 +333,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T warn_once = false; } + uid_data->msaa = g_ActiveConfig.iMultisampleMode > 0; + uid_data->ssaa = g_ActiveConfig.iMultisampleMode > 0 && g_ActiveConfig.bSSAA; if (ApiType == API_OPENGL) { out.Write("out vec4 ocol0;\n"); @@ -347,19 +344,11 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T if (per_pixel_depth) out.Write("#define depth gl_FragDepth\n"); - // We use the flag "centroid" to fix some MSAA rendering bugs. With MSAA, the - // pixel shader will be executed for each pixel which has at least one passed sample. - // So there may be rendered pixels where the center of the pixel isn't in the primitive. - // As the pixel shader usually renders at the center of the pixel, this position may be - // outside the primitive. This will lead to sampling outside the texture, sign changes, ... - // As a workaround, we interpolate at the centroid of the coveraged pixel, which - // is always inside the primitive. - // Without MSAA, this flag is defined to have no effect. uid_data->stereo = g_ActiveConfig.iStereoMode > 0; if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { out.Write("in VertexData {\n"); - GenerateVSOutputMembers<T>(out, ApiType, g_ActiveConfig.backend_info.bSupportsBindingLayout ? "centroid" : "centroid in"); + GenerateVSOutputMembers<T>(out, ApiType, GetInterpolationQualifier(ApiType, true, true)); if (g_ActiveConfig.iStereoMode > 0) out.Write("\tflat int layer;\n"); @@ -368,19 +357,19 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T } else { - out.Write("centroid in float4 colors_0;\n"); - out.Write("centroid in float4 colors_1;\n"); + out.Write("%s in float4 colors_0;\n", GetInterpolationQualifier(ApiType)); + out.Write("%s in float4 colors_1;\n", GetInterpolationQualifier(ApiType)); // compute window position if needed because binding semantic WPOS is not widely supported // Let's set up attributes for (unsigned int i = 0; i < numTexgen; ++i) { - out.Write("centroid in float3 uv%d;\n", i); + out.Write("%s in float3 uv%d;\n", GetInterpolationQualifier(ApiType), i); } - out.Write("centroid in float4 clipPos;\n"); + out.Write("%s in float4 clipPos;\n", GetInterpolationQualifier(ApiType)); if (g_ActiveConfig.bEnablePixelLighting) { - out.Write("centroid in float3 Normal;\n"); - out.Write("centroid in float3 WorldPos;\n"); + out.Write("%s in float3 Normal;\n", GetInterpolationQualifier(ApiType)); + out.Write("%s in float3 WorldPos;\n", GetInterpolationQualifier(ApiType)); } } @@ -401,17 +390,17 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "", per_pixel_depth ? "\n out float depth : SV_Depth," : ""); - out.Write(" in centroid float4 colors_0 : COLOR0,\n"); - out.Write(" in centroid float4 colors_1 : COLOR1\n"); + out.Write(" in %s float4 colors_0 : COLOR0,\n", GetInterpolationQualifier(ApiType)); + out.Write(" in %s float4 colors_1 : COLOR1\n", GetInterpolationQualifier(ApiType)); // compute window position if needed because binding semantic WPOS is not widely supported for (unsigned int i = 0; i < numTexgen; ++i) - out.Write(",\n in centroid float3 uv%d : TEXCOORD%d", i, i); - out.Write(",\n in centroid float4 clipPos : TEXCOORD%d", numTexgen); + out.Write(",\n in %s float3 uv%d : TEXCOORD%d", GetInterpolationQualifier(ApiType), i, i); + out.Write(",\n in %s float4 clipPos : TEXCOORD%d", GetInterpolationQualifier(ApiType), numTexgen); if (g_ActiveConfig.bEnablePixelLighting) { - out.Write(",\n in centroid float3 Normal : TEXCOORD%d", numTexgen + 1); - out.Write(",\n in centroid float3 WorldPos : TEXCOORD%d", numTexgen + 2); + out.Write(",\n in %s float3 Normal : TEXCOORD%d", GetInterpolationQualifier(ApiType), numTexgen + 1); + out.Write(",\n in %s float3 WorldPos : TEXCOORD%d", GetInterpolationQualifier(ApiType), numTexgen + 2); } uid_data->stereo = g_ActiveConfig.iStereoMode > 0; if (g_ActiveConfig.iStereoMode > 0) @@ -499,11 +488,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T if (texcoord < numTexgen) { out.SetConstantsUsed(C_INDTEXSCALE+i/2,C_INDTEXSCALE+i/2); - - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - out.Write("\ttempcoord = irshift(fixpoint_uv%d, " I_INDTEXSCALE"[%d].%s);\n", texcoord, i / 2, (i & 1) ? "zw" : "xy"); - else - out.Write("\ttempcoord = fixpoint_uv%d >> " I_INDTEXSCALE"[%d].%s;\n", texcoord, i / 2, (i & 1) ? "zw" : "xy"); + out.Write("\ttempcoord = fixpoint_uv%d >> " I_INDTEXSCALE"[%d].%s;\n", texcoord, i / 2, (i & 1) ? "zw" : "xy"); } else out.Write("\ttempcoord = int2(0, 0);\n"); @@ -729,22 +714,11 @@ static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, AP int mtxidx = 2*(bpmem.tevind[n].mid-1); out.SetConstantsUsed(C_INDTEXMTX+mtxidx, C_INDTEXMTX+mtxidx); - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - { - out.Write("\tint2 indtevtrans%d = irshift(int2(idot(" I_INDTEXMTX"[%d].xyz, iindtevcrd%d), idot(" I_INDTEXMTX"[%d].xyz, iindtevcrd%d)), 3);\n", n, mtxidx, n, mtxidx+1, n); - - // TODO: should use a shader uid branch for this for better performance - out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = irshift(indtevtrans%d, " I_INDTEXMTX"[%d].w);\n", mtxidx, n, n, mtxidx); - out.Write("\telse indtevtrans%d = ilshift(indtevtrans%d, -" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); - } - else - { - out.Write("\tint2 indtevtrans%d = int2(idot(" I_INDTEXMTX"[%d].xyz, iindtevcrd%d), idot(" I_INDTEXMTX"[%d].xyz, iindtevcrd%d)) >> 3;\n", n, mtxidx, n, mtxidx+1, n); - - // TODO: should use a shader uid branch for this for better performance - out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = indtevtrans%d >> " I_INDTEXMTX"[%d].w;\n", mtxidx, n, n, mtxidx); - out.Write("\telse indtevtrans%d = indtevtrans%d << (-" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); - } + out.Write("\tint2 indtevtrans%d = int2(idot(" I_INDTEXMTX"[%d].xyz, iindtevcrd%d), idot(" I_INDTEXMTX"[%d].xyz, iindtevcrd%d)) >> 3;\n", n, mtxidx, n, mtxidx+1, n); + + // TODO: should use a shader uid branch for this for better performance + out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = indtevtrans%d >> " I_INDTEXMTX"[%d].w;\n", mtxidx, n, n, mtxidx); + out.Write("\telse indtevtrans%d = indtevtrans%d << (-" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); } else if (bpmem.tevind[n].mid <= 7 && bHasTexCoord) { // s matrix @@ -752,20 +726,10 @@ static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, AP int mtxidx = 2*(bpmem.tevind[n].mid-5); out.SetConstantsUsed(C_INDTEXMTX+mtxidx, C_INDTEXMTX+mtxidx); - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - { - out.Write("\tint2 indtevtrans%d = irshift(int2(fixpoint_uv%d * iindtevcrd%d.xx), 8);\n", n, texcoord, n); - - out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = irshift(indtevtrans%d, " I_INDTEXMTX"[%d].w);\n", mtxidx, n, n, mtxidx); - out.Write("\telse indtevtrans%d = ilshift(indtevtrans%d, -" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); - } - else - { - out.Write("\tint2 indtevtrans%d = int2(fixpoint_uv%d * iindtevcrd%d.xx) >> 8;\n", n, texcoord, n); + out.Write("\tint2 indtevtrans%d = int2(fixpoint_uv%d * iindtevcrd%d.xx) >> 8;\n", n, texcoord, n); - out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = indtevtrans%d >> " I_INDTEXMTX"[%d].w;\n", mtxidx, n, n, mtxidx); - out.Write("\telse indtevtrans%d = indtevtrans%d << (-" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); - } + out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = indtevtrans%d >> " I_INDTEXMTX"[%d].w;\n", mtxidx, n, n, mtxidx); + out.Write("\telse indtevtrans%d = indtevtrans%d << (-" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); } else if (bpmem.tevind[n].mid <= 11 && bHasTexCoord) { // t matrix @@ -773,20 +737,10 @@ static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, AP int mtxidx = 2*(bpmem.tevind[n].mid-9); out.SetConstantsUsed(C_INDTEXMTX+mtxidx, C_INDTEXMTX+mtxidx); - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - { - out.Write("\tint2 indtevtrans%d = irshift(int2(fixpoint_uv%d * iindtevcrd%d.yy), 8);\n", n, texcoord, n); + out.Write("\tint2 indtevtrans%d = int2(fixpoint_uv%d * iindtevcrd%d.yy) >> 8;\n", n, texcoord, n); - out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = irshift(indtevtrans%d, " I_INDTEXMTX"[%d].w);\n", mtxidx, n, n, mtxidx); - out.Write("\telse indtevtrans%d = ilshift(indtevtrans%d, -" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); - } - else - { - out.Write("\tint2 indtevtrans%d = int2(fixpoint_uv%d * iindtevcrd%d.yy) >> 8;\n", n, texcoord, n); - - out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = indtevtrans%d >> " I_INDTEXMTX"[%d].w;\n", mtxidx, n, n, mtxidx); - out.Write("\telse indtevtrans%d = indtevtrans%d << (-" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); - } + out.Write("\tif (" I_INDTEXMTX"[%d].w >= 0) indtevtrans%d = indtevtrans%d >> " I_INDTEXMTX"[%d].w;\n", mtxidx, n, n, mtxidx); + out.Write("\telse indtevtrans%d = indtevtrans%d << (-" I_INDTEXMTX"[%d].w);\n", n, n, mtxidx); } else { @@ -825,10 +779,7 @@ static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, AP out.Write("\ttevcoord.xy = wrappedcoord + indtevtrans%d;\n", n); // Emulate s24 overflows - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - out.Write("\ttevcoord.xy = irshift(ilshift(tevcoord.xy, 8), 8);\n"); - else - out.Write("\ttevcoord.xy = (tevcoord.xy << 8) >> 8;\n"); + out.Write("\ttevcoord.xy = (tevcoord.xy << 8) >> 8;\n"); } TevStageCombiner::ColorCombiner &cc = bpmem.combiners[n].colorC; @@ -923,14 +874,14 @@ static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, AP out.SetConstantsUsed(C_COLORS+ac.dest, C_COLORS+ac.dest); - out.Write("\ttevin_a = int4(%s, %s)&255;\n", tevCInputTable[cc.a], tevAInputTable[ac.a]); - out.Write("\ttevin_b = int4(%s, %s)&255;\n", tevCInputTable[cc.b], tevAInputTable[ac.b]); - out.Write("\ttevin_c = int4(%s, %s)&255;\n", tevCInputTable[cc.c], tevAInputTable[ac.c]); + out.Write("\ttevin_a = int4(%s, %s)&int4(255, 255, 255, 255);\n", tevCInputTable[cc.a], tevAInputTable[ac.a]); + out.Write("\ttevin_b = int4(%s, %s)&int4(255, 255, 255, 255);\n", tevCInputTable[cc.b], tevAInputTable[ac.b]); + out.Write("\ttevin_c = int4(%s, %s)&int4(255, 255, 255, 255);\n", tevCInputTable[cc.c], tevAInputTable[ac.c]); out.Write("\ttevin_d = int4(%s, %s);\n", tevCInputTable[cc.d], tevAInputTable[ac.d]); out.Write("\t// color combine\n"); out.Write("\t%s = clamp(", tevCOutputTable[cc.dest]); - if (cc.bias != TevBias_COMPARE) + if (cc.bias != TEVBIAS_COMPARE) { WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.shift); } @@ -960,7 +911,7 @@ static inline void WriteStage(T& out, pixel_shader_uid_data* uid_data, int n, AP out.Write("\t// alpha combine\n"); out.Write("\t%s = clamp(", tevAOutputTable[ac.dest]); - if (ac.bias != TevBias_COMPARE) + if (ac.bias != TEVBIAS_COMPARE) { WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.shift); } @@ -1035,37 +986,12 @@ static inline void WriteTevRegular(T& out, const char* components, int bias, int // - 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 // - a rounding bias is added before dividing by 256 - - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - { - // Haxx - cleaner code by not having irshift and ilshift in the emitted code by omitting them if not used. - const char* leftShift = tevScaleTableLeft[shift]; - const char* rightShift = tevScaleTableRight[shift]; - - if (rightShift[0]) - out.Write("irshift(((tevin_d.%s%s)%s)", components, tevBiasTable[bias], tevScaleTableLeft[shift]); - else - out.Write("((tevin_d.%s%s)%s)", components, tevBiasTable[bias], tevScaleTableLeft[shift]); - out.Write(" %s ", tevOpTable[op]); - if (leftShift[0]) - out.Write("irshift((ilshift((ilshift(tevin_a.%s, 8) + (tevin_b.%s-tevin_a.%s)*(tevin_c.%s+irshift(tevin_c.%s, 7))), %s)%s), 8)", - components, components, components, components, components, - leftShift+4, tevLerpBias[2*op+(shift!=3)]); - else - out.Write("irshift(((ilshift(tevin_a.%s, 8) + (tevin_b.%s-tevin_a.%s)*(tevin_c.%s+irshift(tevin_c.%s, 7)))%s), 8)", - components, components, components, components, components, tevLerpBias[2*op+(shift!=3)]); - if (rightShift[0]) - out.Write(", %s)", rightShift+4); - } - else - { - out.Write("(((tevin_d.%s%s)%s)", components, tevBiasTable[bias], tevScaleTableLeft[shift]); - out.Write(" %s ", tevOpTable[op]); - 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], tevLerpBias[2*op+(shift!=3)]); - out.Write(")%s", tevScaleTableRight[shift]); - } + out.Write("(((tevin_d.%s%s)%s)", components, tevBiasTable[bias], tevScaleTableLeft[shift]); + out.Write(" %s ", tevOpTable[op]); + 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], tevLerpBias[2*op+(shift!=3)]); + out.Write(")%s", tevScaleTableRight[shift]); } template<class T> @@ -1081,14 +1007,14 @@ static inline void SampleTexture(T& out, const char *texcoords, const char *texs static const char *tevAlphaFuncsTable[] = { - "(false)", // NEVER - "(prev.a < %s)", // LESS - "(prev.a == %s)", // EQUAL - "(prev.a <= %s)", // LEQUAL - "(prev.a > %s)", // GREATER - "(prev.a != %s)", // NEQUAL - "(prev.a >= %s)", // GEQUAL - "(true)" // ALWAYS + "(false)", // NEVER + "(prev.a < %s)", // LESS + "(prev.a == %s)", // EQUAL + "(prev.a <= %s)", // LEQUAL + "(prev.a > %s)", // GREATER + "(prev.a != %s)", // NEQUAL + "(prev.a >= %s)", // GEQUAL + "(true)" // ALWAYS }; static const char *tevAlphaFunclogicTable[] = @@ -1228,10 +1154,7 @@ static inline void WriteFog(T& out, pixel_shader_uid_data* uid_data) } out.Write("\tint ifog = iround(fog * 256.0);\n"); - if (DriverDetails::HasBug(DriverDetails::BUG_BROKENIVECSHIFTS)) - out.Write("\tprev.rgb = irshift((prev.rgb * (256 - ifog) + " I_FOGCOLOR".rgb * ifog), 8);\n"); - else - out.Write("\tprev.rgb = (prev.rgb * (256 - ifog) + " I_FOGCOLOR".rgb * ifog) >> 8;\n"); + out.Write("\tprev.rgb = (prev.rgb * (256 - ifog) + " I_FOGCOLOR".rgb * ifog) >> 8;\n"); } void GetPixelShaderUid(PixelShaderUid& object, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components) |
