From 88c7afd315d06c27e459a8352f753cdeca5a1fe5 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 3 Jan 2015 06:06:56 +1300 Subject: [PATCH] Make zfreeze use screenspace coordinates independant of IR. OpenGL requires the y coordinates to be flipped. Also refactored PixelGen code to remove duplicate code. --- Source/Core/VideoBackends/D3D/Render.cpp | 4 ++ Source/Core/VideoBackends/OGL/Render.cpp | 5 +++ Source/Core/VideoCommon/ConstantManager.h | 1 + Source/Core/VideoCommon/PixelShaderGen.cpp | 43 ++++++++++++------- Source/Core/VideoCommon/PixelShaderGen.h | 3 +- .../Core/VideoCommon/PixelShaderManager.cpp | 15 +++++++ Source/Core/VideoCommon/PixelShaderManager.h | 2 + Source/Core/VideoCommon/ShaderGenCommon.h | 1 + 8 files changed, 57 insertions(+), 17 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 268a408022..ea6bb924b6 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -33,6 +33,7 @@ #include "VideoCommon/ImageWrite.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/PixelEngine.h" +#include "VideoCommon/PixelShaderManager.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexShaderManager.h" #include "VideoCommon/VideoConfig.h" @@ -231,6 +232,7 @@ Renderer::Renderer(void *&window_handle) s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; s_last_xfb_mode = g_ActiveConfig.bUseRealXFB; CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); + PixelShaderManager::SetEfbScaleChanged(); SetupDeviceObjects(); @@ -946,6 +948,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co s_last_stereo_mode = g_ActiveConfig.iStereoMode > 0; CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); + PixelShaderManager::SetEfbScaleChanged(); + D3D::context->OMSetRenderTargets(1, &D3D::GetBackBuffer()->GetRTV(), nullptr); delete g_framebuffer_manager; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 961d50f9c7..3d1991fe3f 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -43,6 +43,7 @@ #include "VideoCommon/ImageWrite.h" #include "VideoCommon/OnScreenDisplay.h" #include "VideoCommon/PixelEngine.h" +#include "VideoCommon/PixelShaderManager.h" #include "VideoCommon/Statistics.h" #include "VideoCommon/VertexLoaderManager.h" #include "VideoCommon/VertexShaderGen.h" @@ -618,6 +619,8 @@ Renderer::Renderer() s_last_efb_scale = g_ActiveConfig.iEFBScale; CalculateTargetSize(s_backbuffer_width, s_backbuffer_height); + PixelShaderManager::SetEfbScaleChanged(); + // Because of the fixed framebuffer size we need to disable the resolution // options while running g_Config.bRunning = true; @@ -1681,6 +1684,8 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co delete g_framebuffer_manager; g_framebuffer_manager = new FramebufferManager(s_target_width, s_target_height, s_MSAASamples); + + PixelShaderManager::SetEfbScaleChanged(); } } diff --git a/Source/Core/VideoCommon/ConstantManager.h b/Source/Core/VideoCommon/ConstantManager.h index b7b3d6664c..8fc1c221ed 100644 --- a/Source/Core/VideoCommon/ConstantManager.h +++ b/Source/Core/VideoCommon/ConstantManager.h @@ -24,6 +24,7 @@ struct PixelShaderConstants int4 fogi; float4 fogf[2]; float4 zslope; + float4 efbscale; }; struct VertexShaderConstants diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index 8bc7a7980b..5899f0100b 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -144,6 +144,7 @@ template static inline void WriteTevRegular(T& out, const char* compone template static inline void SampleTexture(T& out, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType); template static inline void WriteAlphaTest(T& out, pixel_shader_uid_data* uid_data, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth); template static inline void WriteFog(T& out, pixel_shader_uid_data* uid_data); +template static inline void WritePerPixelDepth(T& out, pixel_shader_uid_data* uid_data, API_TYPE ApiType); template static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components) @@ -229,6 +230,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T "\tint4 " I_FOGI";\n" "\tfloat4 " I_FOGF"[2];\n" "\tfloat4 " I_ZSLOPE";\n" + "\tfloat4 " I_EFBSCALE";\n" "};\n"); if (g_ActiveConfig.bEnablePixelLighting) @@ -544,14 +546,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // Note: z-textures are not written to depth buffer if early depth test is used if (per_pixel_depth && bpmem.UseEarlyDepthTest()) { - if (bpmem.genMode.zfreeze) - { - out.Write("\tdepth = float(" I_ZSLOPE".z + " I_ZSLOPE".x * rawpos.x + " I_ZSLOPE".y * rawpos.y) / float(0xffffff);\n"); - } - else - { - out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n"); - } + WritePerPixelDepth(out, uid_data, ApiType); } // Note: depth texture output is only written to depth buffer if late depth test is used @@ -567,14 +562,7 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T if (per_pixel_depth && bpmem.UseLateDepthTest()) { - if (bpmem.genMode.zfreeze) - { - out.Write("\tdepth = float(" I_ZSLOPE".z + " I_ZSLOPE".x * rawpos.x + " I_ZSLOPE".y * rawpos.y) / float(0xffffff);\n"); - } - else - { - out.Write("\tdepth = float(zCoord) / float(0xFFFFFF);\n"); - } + WritePerPixelDepth(out, uid_data, ApiType); } if (dstAlphaMode == DSTALPHA_ALPHA_PASS) @@ -1115,6 +1103,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 +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 - 1;\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(object, dstAlphaMode, ApiType, components); diff --git a/Source/Core/VideoCommon/PixelShaderGen.h b/Source/Core/VideoCommon/PixelShaderGen.h index eb787fdc81..f8631e73a8 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.h +++ b/Source/Core/VideoCommon/PixelShaderGen.h @@ -22,8 +22,9 @@ #define C_FOGI (C_FOGCOLOR + 1) //28 #define C_FOGF (C_FOGI + 2) //29 #define C_ZSLOPE (C_FOGF + 1) //31 +#define C_EFBSCALE (C_ZSLOPE + 1) //32 -#define C_PENVCONST_END (C_ZSLOPE + 2) +#define C_PENVCONST_END (C_EFBSCALE + 1) // Different ways to achieve rendering with destination alpha enum DSTALPHA_MODE diff --git a/Source/Core/VideoCommon/PixelShaderManager.cpp b/Source/Core/VideoCommon/PixelShaderManager.cpp index d0004a0921..a94dfaf991 100644 --- a/Source/Core/VideoCommon/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/PixelShaderManager.cpp @@ -14,6 +14,7 @@ bool PixelShaderManager::s_bFogRangeAdjustChanged; bool PixelShaderManager::s_bViewPortChanged; +bool PixelShaderManager::s_bEFBScaleChanged; std::array PixelShaderManager::s_tev_color; std::array PixelShaderManager::s_tev_konst_color; @@ -48,6 +49,7 @@ void PixelShaderManager::Dirty() SetDestAlpha(); SetZTextureBias(); SetViewportChanged(); + SetEfbScaleChanged(); SetZSlope(0, 0, 1); SetIndTexScaleChanged(false); SetIndTexScaleChanged(true); @@ -113,6 +115,13 @@ void PixelShaderManager::SetConstants() dirty = true; s_bViewPortChanged = false; } + + if (s_bEFBScaleChanged) { + constants.efbscale[0] = 1.0f / float(Renderer::EFBToScaledXf(1)); + constants.efbscale[1] = 1.0f / float(Renderer::EFBToScaledYf(1)); + dirty = true; + s_bEFBScaleChanged = false; + } } void PixelShaderManager::SetTevColor(int index, int component, s32 value) @@ -169,6 +178,12 @@ void PixelShaderManager::SetViewportChanged() s_bFogRangeAdjustChanged = true; // TODO: Shouldn't be necessary with an accurate fog range adjust implementation } +void PixelShaderManager::SetEfbScaleChanged() +{ + s_bEFBScaleChanged = true; + s_bViewPortChanged = true; +} + void PixelShaderManager::SetZSlope(float dfdx, float dfdy, float f0) { constants.zslope[0] = dfdx; diff --git a/Source/Core/VideoCommon/PixelShaderManager.h b/Source/Core/VideoCommon/PixelShaderManager.h index faa15cff7e..421fd3393c 100644 --- a/Source/Core/VideoCommon/PixelShaderManager.h +++ b/Source/Core/VideoCommon/PixelShaderManager.h @@ -36,6 +36,7 @@ public: static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt); static void SetZTextureBias(); static void SetViewportChanged(); + static void SetEfbScaleChanged(); static void SetZSlope(float dfdx, float dfdy, float f0); static void SetIndMatrixChanged(int matrixidx); static void SetTevKSelChanged(int id); @@ -51,6 +52,7 @@ public: static bool s_bFogRangeAdjustChanged; static bool s_bViewPortChanged; + static bool s_bEFBScaleChanged; // These colors aren't available from global BP state, // hence we keep a copy of them around. diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h index dd80fd3987..4698392f9e 100644 --- a/Source/Core/VideoCommon/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/ShaderGenCommon.h @@ -292,6 +292,7 @@ static inline void AssignVSOutputMembers(T& object, const char* a, const char* b #define I_FOGI "cfogi" #define I_FOGF "cfogf" #define I_ZSLOPE "czslope" +#define I_EFBSCALE "cefbscale" #define I_POSNORMALMATRIX "cpnmtx" #define I_PROJECTION "cproj"