summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/PixelShaderGen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Core/VideoCommon/PixelShaderGen.cpp')
-rw-r--r--Source/Core/VideoCommon/PixelShaderGen.cpp51
1 files changed, 45 insertions, 6 deletions
diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp
index edc67cc83c..7c76628dd4 100644
--- a/Source/Core/VideoCommon/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/PixelShaderGen.cpp
@@ -144,6 +144,7 @@ template<class T> static inline void WriteTevRegular(T& out, const char* compone
template<class T> static inline void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
template<class T> static inline void WriteAlphaTest(T& out, pixel_shader_uid_data* uid_data, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth);
template<class T> static inline void WriteFog(T& out, pixel_shader_uid_data* uid_data);
+template<class T> static inline void WritePerPixelDepth(T& out, pixel_shader_uid_data* uid_data, API_TYPE ApiType);
template<class T>
static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
@@ -228,6 +229,8 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
"\tint4 " I_FOGCOLOR";\n"
"\tint4 " I_FOGI";\n"
"\tfloat4 " I_FOGF"[2];\n"
+ "\tfloat4 " I_ZSLOPE";\n"
+ "\tfloat4 " I_EFBSCALE";\n"
"};\n");
if (g_ActiveConfig.bEnablePixelLighting)
@@ -268,8 +271,12 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
GenerateVSOutputMembers<T>(out, ApiType);
out.Write("};\n");
- const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest() && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED);
- const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z);
+ const bool forced_early_z = g_ActiveConfig.backend_info.bSupportsEarlyZ && bpmem.UseEarlyDepthTest()
+ && (g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED)
+ // We can't allow early_ztest for zfreeze because depth is overridden per-pixel.
+ // This means it's impossible for zcomploc to be emulated on a zfrozen polygon.
+ && !bpmem.genMode.zfreeze;
+ const bool per_pixel_depth = (bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) || (!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z) || bpmem.genMode.zfreeze;
if (forced_early_z)
{
@@ -362,7 +369,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
out.Write("void main(\n");
out.Write(" out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
- per_pixel_depth ? "\n out float depth : SV_Depth," : "");
+ (per_pixel_depth && bpmem.zmode.testenable) ? "\n out float depth : SV_Depth," : "");
out.Write(" in centroid float4 colors_0 : COLOR0,\n");
out.Write(" in centroid float4 colors_1 : COLOR1\n");
@@ -538,10 +545,13 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
uid_data->fast_depth_calc = g_ActiveConfig.bFastDepthCalc;
uid_data->early_ztest = bpmem.UseEarlyDepthTest();
uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel;
+ uid_data->zfreeze = bpmem.genMode.zfreeze;
// Note: z-textures are not written to depth buffer if early depth test is used
if (per_pixel_depth && bpmem.UseEarlyDepthTest())
- out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n");
+ {
+ WritePerPixelDepth<T>(out, uid_data, ApiType);
+ }
// Note: depth texture output is only written to depth buffer if late depth test is used
// theoretical final depth value is used for fog calculation, though, so we have to emulate ztextures anyway
@@ -555,7 +565,9 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T
}
if (per_pixel_depth && bpmem.UseLateDepthTest())
- out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n");
+ {
+ WritePerPixelDepth<T>(out, uid_data, ApiType);
+ }
if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
{
@@ -1015,7 +1027,11 @@ static inline void WriteAlphaTest(T& out, pixel_shader_uid_data* uid_data, API_T
// Tests seem to have proven that writing depth even when the alpha test fails is more
// important that a reliable alpha test, so we just force the alpha test to always succeed.
// At least this seems to be less buggy.
- uid_data->alpha_test_use_zcomploc_hack = bpmem.UseEarlyDepthTest() && bpmem.zmode.updateenable && !g_ActiveConfig.backend_info.bSupportsEarlyZ;
+ uid_data->alpha_test_use_zcomploc_hack = bpmem.UseEarlyDepthTest()
+ && bpmem.zmode.updateenable
+ && !g_ActiveConfig.backend_info.bSupportsEarlyZ
+ && !bpmem.genMode.zfreeze;
+
if (!uid_data->alpha_test_use_zcomploc_hack)
{
out.Write("\t\tdiscard;\n");
@@ -1095,6 +1111,29 @@ static inline void WriteFog(T& out, pixel_shader_uid_data* uid_data)
out.Write("\tprev.rgb = (prev.rgb * (256 - ifog) + " I_FOGCOLOR".rgb * ifog) >> 8;\n");
}
+template<class T>
+static inline void WritePerPixelDepth(T& out, pixel_shader_uid_data* uid_data, API_TYPE ApiType)
+{
+ if (bpmem.genMode.zfreeze)
+ {
+ out.SetConstantsUsed(C_ZSLOPE, C_ZSLOPE);
+ out.SetConstantsUsed(C_EFBSCALE, C_EFBSCALE);
+
+ out.Write("\tfloat2 screenpos = rawpos.xy * " I_EFBSCALE".xy;\n");
+
+ // Opengl has reversed vertical screenspace coordiantes
+ if (ApiType == API_OPENGL)
+ out.Write("\tscreenpos.y = %i - screenpos.y;\n", EFB_HEIGHT);
+
+ out.Write("\tdepth = float(" I_ZSLOPE".z + " I_ZSLOPE".x * screenpos.x + " I_ZSLOPE".y * screenpos.y) / float(0xFFFFFF);\n");
+ }
+ else
+ {
+ out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n");
+ }
+}
+
+
void GetPixelShaderUid(PixelShaderUid& object, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
{
GeneratePixelShader<PixelShaderUid>(object, dstAlphaMode, ApiType, components);