From 2975e530914778f9abaa1aedf6a6c947559ef7ab Mon Sep 17 00:00:00 2001 From: galop1n Date: Sun, 24 May 2015 14:44:25 +0200 Subject: [PATCH 1/2] D3D: Depth range inversion. Credits go to Galop1n for designing this technique and to BhaaLseN for cleaning up the commit. --- Source/Core/VideoBackends/D3D/D3DState.cpp | 10 +++++----- .../Core/VideoBackends/D3D/PixelShaderCache.cpp | 4 ++-- Source/Core/VideoBackends/D3D/Render.cpp | 9 +++++---- Source/Core/VideoCommon/PixelShaderGen.cpp | 17 +++++++++++++---- .../VideoCommon/TextureConversionShader.cpp | 10 ++++++++++ Source/Core/VideoCommon/VertexShaderGen.cpp | 2 +- 6 files changed, 36 insertions(+), 16 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/D3DState.cpp b/Source/Core/VideoBackends/D3D/D3DState.cpp index 34e0eb7680..bd0a80b355 100644 --- a/Source/Core/VideoBackends/D3D/D3DState.cpp +++ b/Source/Core/VideoBackends/D3D/D3DState.cpp @@ -433,7 +433,7 @@ ID3D11DepthStencilState* StateCache::Get(ZMode state) depthdc.DepthEnable = TRUE; depthdc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; - depthdc.DepthFunc = D3D11_COMPARISON_LESS; + depthdc.DepthFunc = D3D11_COMPARISON_GREATER; depthdc.StencilEnable = FALSE; depthdc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; depthdc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; @@ -441,12 +441,12 @@ ID3D11DepthStencilState* StateCache::Get(ZMode state) const D3D11_COMPARISON_FUNC d3dCmpFuncs[8] = { D3D11_COMPARISON_NEVER, - D3D11_COMPARISON_LESS, - D3D11_COMPARISON_EQUAL, - D3D11_COMPARISON_LESS_EQUAL, D3D11_COMPARISON_GREATER, - D3D11_COMPARISON_NOT_EQUAL, + D3D11_COMPARISON_EQUAL, D3D11_COMPARISON_GREATER_EQUAL, + D3D11_COMPARISON_LESS, + D3D11_COMPARISON_NOT_EQUAL, + D3D11_COMPARISON_LESS_EQUAL, D3D11_COMPARISON_ALWAYS }; diff --git a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp index b1d0cf4cd9..918432bb77 100644 --- a/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/PixelShaderCache.cpp @@ -146,7 +146,7 @@ const char depth_matrix_program[] = { " in float4 pos : SV_Position,\n" " in float3 uv0 : TEXCOORD0){\n" " float4 texcol = Tex0.Sample(samp0,uv0);\n" - " int depth = clamp(int(texcol.x * 16777216.0), 0, 0xFFFFFF);\n" + " int depth = clamp(int((1.0 - texcol.x) * 16777216.0), 0, 0xFFFFFF);\n" // Convert to Z24 format " int4 workspace;\n" @@ -180,7 +180,7 @@ const char depth_matrix_program_msaa[] = { " for(int i = 0; i < SAMPLES; ++i)\n" " texcol += Tex0.Load(int3(uv0.x*(width), uv0.y*(height), uv0.z), i);\n" " texcol /= SAMPLES;\n" - " int depth = clamp(int(texcol.x * 16777216.0), 0, 0xFFFFFF);\n" + " int depth = clamp(int((1.0 - texcol.x) * 16777216.0), 0, 0xFFFFFF);\n" // Convert to Z24 format " int4 workspace;\n" diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index 6bda211de6..cc06c077d1 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -415,7 +415,8 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) // read the data from system memory D3D::context->Map(read_tex, 0, D3D11_MAP_READ, 0, &map); - float val = *(float*)map.pData; + // depth buffer is inverted in the d3d backend + float val = 1.0f - *(float*)map.pData; u32 ret = 0; if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16) { @@ -522,8 +523,8 @@ void Renderer::SetViewport() Ht = (Y + Ht <= GetTargetHeight()) ? Ht : (GetTargetHeight() - Y); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(X, Y, Wd, Ht, - MathUtil::Clamp(xfmem.viewport.farZ - xfmem.viewport.zRange, 0.0f, 16777215.0f) / 16777216.0f, - MathUtil::Clamp(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f); + 1.0f - MathUtil::Clamp(xfmem.viewport.farZ, 0.0f, 16777215.0f) / 16777216.0f, + 1.0f - MathUtil::Clamp(xfmem.viewport.farZ - xfmem.viewport.zRange, 0.0f, 16777215.0f) / 16777216.0f); D3D::context->RSSetViewports(1, &vp); } @@ -548,7 +549,7 @@ void Renderer::ClearScreen(const EFBRectangle& rc, bool colorEnable, bool alphaE // Color is passed in bgra mode so we need to convert it to rgba u32 rgbaColor = (color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000); - D3D::drawClearQuad(rgbaColor, (z & 0xFFFFFF) / 16777216.0f); + D3D::drawClearQuad(rgbaColor, 1.0f - (z & 0xFFFFFF) / 16777216.0f); D3D::stateman->PopDepthState(); D3D::stateman->PopBlendState(); diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index ecb47d5584..d9d8c18599 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -582,7 +582,10 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T } else { - out.Write("\tint zCoord = int(rawpos.z * 16777216.0);\n"); + if (ApiType == API_D3D) + out.Write("\tint zCoord = int((1.0 - rawpos.z) * 16777216.0);\n"); + else + out.Write("\tint zCoord = int(rawpos.z * 16777216.0);\n"); } out.Write("\tzCoord = clamp(zCoord, " I_ZBIAS"[1].x - " I_ZBIAS"[1].y, " I_ZBIAS"[1].x);\n"); @@ -600,7 +603,10 @@ 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()) { - out.Write("\tdepth = float(zCoord) / 16777216.0;\n"); + if (ApiType == API_D3D) + out.Write("\tdepth = 1.0 - float(zCoord) / 16777216.0;\n"); + else + out.Write("\tdepth = float(zCoord) / 16777216.0;\n"); } // Note: depth texture output is only written to depth buffer if late depth test is used @@ -616,7 +622,10 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T if (per_pixel_depth && bpmem.UseLateDepthTest()) { - out.Write("\tdepth = float(zCoord) / 16777216.0;\n"); + if (ApiType == API_D3D) + out.Write("\tdepth = 1.0 - float(zCoord) / 16777216.0;\n"); + else + out.Write("\tdepth = float(zCoord) / 16777216.0;\n"); } if (dstAlphaMode == DSTALPHA_ALPHA_PASS) @@ -1129,7 +1138,7 @@ static inline void WriteAlphaTest(T& out, pixel_shader_uid_data* uid_data, API_T if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND) out.Write("\t\tocol1 = float4(0.0, 0.0, 0.0, 0.0);\n"); if (per_pixel_depth) - out.Write("\t\tdepth = 1.0;\n"); + out.Write("\t\tdepth = %s;\n", (ApiType == API_D3D) ? "0.0" : "1.0"); // ZCOMPLOC HACK: // The only way to emulate alpha test + early-z is to force early-z in the shader. diff --git a/Source/Core/VideoCommon/TextureConversionShader.cpp b/Source/Core/VideoCommon/TextureConversionShader.cpp index fac5a0823c..f93d465a16 100644 --- a/Source/Core/VideoCommon/TextureConversionShader.cpp +++ b/Source/Core/VideoCommon/TextureConversionShader.cpp @@ -462,15 +462,19 @@ static void WriteZ8Encoder(char*& p, const char* multiplier,API_TYPE ApiType) WRITE(p, " float depth;\n"); WriteSampleColor(p, "r", "depth", 0, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, "ocol0.b = frac(depth * %s);\n", multiplier); WriteSampleColor(p, "r", "depth", 1, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, "ocol0.g = frac(depth * %s);\n", multiplier); WriteSampleColor(p, "r", "depth", 2, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, "ocol0.r = frac(depth * %s);\n", multiplier); WriteSampleColor(p, "r", "depth", 3, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, "ocol0.a = frac(depth * %s);\n", multiplier); WriteEncoderEnd(p, ApiType); @@ -486,6 +490,7 @@ static void WriteZ16Encoder(char*& p,API_TYPE ApiType) // byte order is reversed WriteSampleColor(p, "r", "depth", 0, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, " depth = clamp(depth * 16777216.0, 0.0, float(0xFFFFFF));\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -496,6 +501,7 @@ static void WriteZ16Encoder(char*& p,API_TYPE ApiType) WRITE(p, " ocol0.g = expanded.r / 255.0;\n"); WriteSampleColor(p, "r", "depth", 1, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, " depth = clamp(depth * 16777216.0, 0.0, float(0xFFFFFF));\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -518,6 +524,7 @@ static void WriteZ16LEncoder(char*& p,API_TYPE ApiType) // byte order is reversed WriteSampleColor(p, "r", "depth", 0, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, " depth = clamp(depth * 16777216.0, 0.0, float(0xFFFFFF));\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -530,6 +537,7 @@ static void WriteZ16LEncoder(char*& p,API_TYPE ApiType) WRITE(p, " ocol0.g = expanded.g / 255.0;\n"); WriteSampleColor(p, "r", "depth", 1, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth = 1.0f - depth;\n"); WRITE(p, " depth = clamp(depth * 16777216.0, 0.0, float(0xFFFFFF));\n"); WRITE(p, " expanded.r = floor(depth / (256.0 * 256.0));\n"); @@ -554,7 +562,9 @@ static void WriteZ24Encoder(char*& p, API_TYPE ApiType) WRITE(p, " float3 expanded1;\n"); WriteSampleColor(p, "r", "depth0", 0, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth0 = 1.0f - depth0;\n"); WriteSampleColor(p, "r", "depth1", 1, ApiType); + if (ApiType == API_D3D) WRITE(p, "depth1 = 1.0f - depth1;\n"); for (int i = 0; i < 2; i++) { diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 28c2e1c827..084ac48aaf 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -385,7 +385,7 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ } else if (api_type == API_D3D) { - out.Write("o.pos.z = o.pos.w + o.pos.z;\n"); + out.Write("o.pos.z = -o.pos.z;\n"); } else // OGL { From ca7801da449d214bebdfd2573aeae16cd492bc72 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 25 May 2015 23:29:47 +0200 Subject: [PATCH 2/2] D3D: Invert initial depth buffer clear. --- Source/Core/VideoBackends/D3D/Render.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index cc06c077d1..230cb11ec4 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -259,7 +259,7 @@ Renderer::Renderer(void *&window_handle) // Clear EFB textures float ClearColor[4] = { 0.f, 0.f, 0.f, 1.f }; D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), ClearColor); - D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); + D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 0.f, 0); D3D11_VIEWPORT vp = CD3D11_VIEWPORT(0.f, 0.f, (float)s_target_width, (float)s_target_height); D3D::context->RSSetViewports(1, &vp); @@ -957,7 +957,7 @@ void Renderer::SwapImpl(u32 xfbAddr, u32 fbWidth, u32 fbStride, u32 fbHeight, co g_framebuffer_manager = new FramebufferManager; float clear_col[4] = { 0.f, 0.f, 0.f, 1.f }; D3D::context->ClearRenderTargetView(FramebufferManager::GetEFBColorTexture()->GetRTV(), clear_col); - D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 1.f, 0); + D3D::context->ClearDepthStencilView(FramebufferManager::GetEFBDepthTexture()->GetDSV(), D3D11_CLEAR_DEPTH, 0.f, 0); } // begin next frame