From c709270a9f0533ac802a0b3b9a143d1981966b1a Mon Sep 17 00:00:00 2001 From: Nicklas Lindgren Date: Thu, 29 Dec 2016 19:15:07 +0100 Subject: [PATCH 1/2] Fix crash for DOF blur at default DOF resolution Initialization of GAUSS (the DOF blur filter) would fail and cause a crash at startup if dofBlurAmount was set to anything larger than zero and the dofOverrideResolution was zero or unspecified. This change treats the DOF resolution as 360 when configured as zero for the purpose of initializing the blur filter and detecting the DOF render targets. --- RenderstateManager.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/RenderstateManager.cpp b/RenderstateManager.cpp index 634fe1a..518c2ee 100644 --- a/RenderstateManager.cpp +++ b/RenderstateManager.cpp @@ -15,15 +15,26 @@ RSManager RSManager::instance; -static const char *PIXEL_SHADER_DUMP_DIR = "dsfix/pixelshader_dump"; -static const char *PIXEL_SHADER_OVERRIDE_DIR = "dsfix/pixelshader_override"; -static const char *VERTEX_SHADER_DUMP_DIR = "dsfix/vertexshader_dump"; -static const char *VERTEX_SHADER_OVERRIDE_DIR = "dsfix/vertexshader_override"; +namespace { + const char *PIXEL_SHADER_DUMP_DIR = "dsfix/pixelshader_dump"; + const char *PIXEL_SHADER_OVERRIDE_DIR = "dsfix/pixelshader_override"; + const char *VERTEX_SHADER_DUMP_DIR = "dsfix/vertexshader_dump"; + const char *VERTEX_SHADER_OVERRIDE_DIR = "dsfix/vertexshader_override"; + + unsigned getDOFResolution() { + unsigned setting = Settings::get().getDOFOverrideResolution(); + if (setting == 0) { + return 360; + } else { + return setting; + } + } +} void RSManager::initResources() { SDLOG(0, "RenderstateManager resource initialization started\n"); unsigned rw = Settings::get().getRenderWidth(), rh = Settings::get().getRenderHeight(); - unsigned dofRes = Settings::get().getDOFOverrideResolution(); + unsigned dofRes = getDOFResolution(); if(Settings::get().getAAQuality()) { if(Settings::get().getAAType() == "SMAA") { smaa = new SMAA(d3ddev, rw, rh, (SMAA::Preset)(Settings::get().getAAQuality()-1)); @@ -581,7 +592,7 @@ void RSManager::reloadScao() { void RSManager::reloadGauss() { SAFEDELETE(gauss); - gauss = new GAUSS(d3ddev, Settings::get().getDOFOverrideResolution()*16/9, Settings::get().getDOFOverrideResolution()); + gauss = new GAUSS(d3ddev, getDOFResolution()*16/9, getDOFResolution()); SDLOG(0, "Reloaded GAUSS\n"); } @@ -754,7 +765,7 @@ bool RSManager::isTextureText(IDirect3DBaseTexture9* t) { } unsigned RSManager::isDof(unsigned width, unsigned height) { - unsigned topWidth = Settings::get().getDOFOverrideResolution()*16/9, topHeight = Settings::get().getDOFOverrideResolution(); + unsigned topWidth = getDOFResolution()*16/9, topHeight = getDOFResolution(); if(width == topWidth && height == topHeight) return 1; if(width == topWidth/2 && height == topHeight/2) return 2; return 0; From 3e53a69b13300dac700e2d20f8d607aff9810c7b Mon Sep 17 00:00:00 2001 From: Nicklas Lindgren Date: Mon, 2 Jan 2017 06:37:11 +0100 Subject: [PATCH 2/2] Fix drawing of sun and lens flares Whether the sun and lens flares are drawn are determined by the result of an occlusion query. If the query returns a larger number of pixels drawn than expected, which often happens when running in a higher resolution than the default, the sun and lens flares might not be drawn. This change wraps the IDirect3DQuery9 objects used for occlusion queries and modifies the returned number of pixels drawn to correspond with the default resolution, which makes the sun and lens flares appear as expected. --- DSfix.vcxproj | 2 ++ RenderstateManager.cpp | 1 + RenderstateManager.h | 5 ++++- d3d9.h | 1 + d3d9dev.cpp | 7 ++++++- d3d9query.cpp | 46 ++++++++++++++++++++++++++++++++++++++++++ d3d9query.h | 19 +++++++++++++++++ 7 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 d3d9query.cpp create mode 100644 d3d9query.h diff --git a/DSfix.vcxproj b/DSfix.vcxproj index ce32a8a..346d85e 100644 --- a/DSfix.vcxproj +++ b/DSfix.vcxproj @@ -251,6 +251,7 @@ WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL WIN32;NDEBUG;_WINDOWS;_MBCS;_USRDLL + @@ -313,6 +314,7 @@ + diff --git a/RenderstateManager.cpp b/RenderstateManager.cpp index 518c2ee..cb2ad8d 100644 --- a/RenderstateManager.cpp +++ b/RenderstateManager.cpp @@ -34,6 +34,7 @@ namespace { void RSManager::initResources() { SDLOG(0, "RenderstateManager resource initialization started\n"); unsigned rw = Settings::get().getRenderWidth(), rh = Settings::get().getRenderHeight(); + areaScale = rw * rh / 1024.0 / 576.0; unsigned dofRes = getDOFResolution(); if(Settings::get().getAAQuality()) { if(Settings::get().getAAType() == "SMAA") { diff --git a/RenderstateManager.h b/RenderstateManager.h index 63c950c..2b1b6b8 100644 --- a/RenderstateManager.h +++ b/RenderstateManager.h @@ -117,6 +117,7 @@ class RSManager { void dumpShader(UINT32 hash, const char *directory, LPD3DXBUFFER pBuffer); bool getOverrideShader(UINT32 hash, const char *directory, LPD3DXBUFFER *ppBuffer); + float areaScale; private: ~RSManager(); @@ -127,7 +128,7 @@ class RSManager { RSManager() : smaa(NULL), fxaa(NULL), ssao(NULL), gauss(NULL), rgbaBuffer1Surf(NULL), rgbaBuffer1Tex(NULL), inited(false), doAA(true), doSsao(true), doDofGauss(true), doHud(true), captureNextFrame(false), capturing(false), hudStarted(false), takeScreenshot(false), hideHud(false), - mainRenderTexIndex(0), mainRenderSurfIndex(0), dumpCaptureIndex(0), numKnownTextures(0), foundKnownTextures(0), skippedPresents(0) { + mainRenderTexIndex(0), mainRenderSurfIndex(0), dumpCaptureIndex(0), numKnownTextures(0), foundKnownTextures(0), skippedPresents(0), areaScale(1) { #define TEXTURE(_name, _hash) ++numKnownTextures; #include "Textures.def" #undef TEXTURE @@ -195,4 +196,6 @@ class RSManager { HRESULT redirectSetRenderState(D3DRENDERSTATETYPE State, DWORD Value); HRESULT redirectCreatePixelShader(CONST DWORD *pfunction, IDirect3DPixelShader9 **ppShader); HRESULT redirectCreateVertexShader(CONST DWORD *pfunction, IDirect3DVertexShader9 **ppShader); + + float getAreaScale() const { return areaScale; } }; diff --git a/d3d9.h b/d3d9.h index d512f4b..2d142e9 100644 --- a/d3d9.h +++ b/d3d9.h @@ -9,5 +9,6 @@ #include #include "d3d9int.h" #include "d3d9dev.h" +#include "d3d9query.h" IDirect3D9 *APIENTRY hkDirect3DCreate9(UINT SDKVersion); diff --git a/d3d9dev.cpp b/d3d9dev.cpp index 4d1f86a..291258d 100644 --- a/d3d9dev.cpp +++ b/d3d9dev.cpp @@ -186,7 +186,12 @@ HRESULT APIENTRY hkIDirect3DDevice9::CreatePixelShader(CONST DWORD* pFunction,ID } HRESULT APIENTRY hkIDirect3DDevice9::CreateQuery(D3DQUERYTYPE Type,IDirect3DQuery9** ppQuery) { - return m_pD3Ddev->CreateQuery(Type, ppQuery); + auto result = m_pD3Ddev->CreateQuery(Type, ppQuery); + if (Type == D3DQUERYTYPE_OCCLUSION && result == D3D_OK) { + new hkIDirect3DQuery9(ppQuery); + // These instances will leak, but there are only a set number of them created + } + return result; } HRESULT APIENTRY hkIDirect3DDevice9::CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9** ppSurface, HANDLE* pSharedHandle) { diff --git a/d3d9query.cpp b/d3d9query.cpp new file mode 100644 index 0000000..6c3e478 --- /dev/null +++ b/d3d9query.cpp @@ -0,0 +1,46 @@ +#include "d3d9.h" +#include "main.h" +#include "RenderstateManager.h" +#include "Settings.h" + +hkIDirect3DQuery9::hkIDirect3DQuery9(IDirect3DQuery9 **ppReturnedQueryInterface) { + m_pD3Dquery = *ppReturnedQueryInterface; + *ppReturnedQueryInterface = this; +} + +HRESULT APIENTRY hkIDirect3DQuery9::QueryInterface(REFIID riid, void** ppvObj) { + return m_pD3Dquery->QueryInterface(riid, ppvObj); +} + +ULONG APIENTRY hkIDirect3DQuery9::AddRef() { + return m_pD3Dquery->AddRef(); +} + +ULONG APIENTRY hkIDirect3DQuery9::Release() { + return m_pD3Dquery->Release(); +} + +HRESULT APIENTRY hkIDirect3DQuery9::GetDevice(IDirect3DDevice9** ppDevice) { + return m_pD3Dquery->GetDevice(ppDevice); +} + +D3DQUERYTYPE APIENTRY hkIDirect3DQuery9::GetType() { + return m_pD3Dquery->GetType(); +} + +DWORD APIENTRY hkIDirect3DQuery9::GetDataSize() { + return m_pD3Dquery->GetDataSize(); +} + +HRESULT APIENTRY hkIDirect3DQuery9::Issue(DWORD dwIssueFlags) { + return m_pD3Dquery->Issue(dwIssueFlags); +} + +HRESULT APIENTRY hkIDirect3DQuery9::GetData(void* pData, DWORD dwSize, DWORD dwGetDataFlags) { + auto result = m_pD3Dquery->GetData(pData, dwSize, dwGetDataFlags); + if (result == D3D_OK) { + auto pixelsDrawn = reinterpret_cast(pData); + pixelsDrawn[0] = static_cast(pixelsDrawn[0] / RSManager::get().getAreaScale()); + } + return result; +} \ No newline at end of file diff --git a/d3d9query.h b/d3d9query.h new file mode 100644 index 0000000..41c6224 --- /dev/null +++ b/d3d9query.h @@ -0,0 +1,19 @@ +#pragma once + +#include "d3d9.h" + +interface hkIDirect3DQuery9 : public IDirect3DQuery9 +{ + hkIDirect3DQuery9(IDirect3DQuery9 **ppReturnedQueryInterface); + + IDirect3DQuery9* m_pD3Dquery; + + STDMETHOD(QueryInterface)(THIS_ REFIID riid, void** ppvObj); + STDMETHOD_(ULONG, AddRef)(THIS); + STDMETHOD_(ULONG, Release)(THIS); + STDMETHOD(GetDevice)(THIS_ IDirect3DDevice9** ppDevice); + STDMETHOD_(D3DQUERYTYPE, GetType)(THIS); + STDMETHOD_(DWORD, GetDataSize)(THIS); + STDMETHOD(Issue)(THIS_ DWORD dwIssueFlags); + STDMETHOD(GetData)(THIS_ void* pData, DWORD dwSize, DWORD dwGetDataFlags); +}; \ No newline at end of file