6 changed files with 421 additions and 2 deletions
-
4FSR3UnityPlugin.vcxproj
-
6FSR3UnityPlugin.vcxproj.filters
-
92include/SwapChainTrampoline.h
-
91src/FSR3UnityPlugin.cpp
-
3src/FSR3UnityTypes.h
-
227src/SwapChainTrampoline.cpp
@ -0,0 +1,92 @@ |
|||
#pragma once |
|||
|
|||
#include <d3d12.h> |
|||
#include <dxgi1_5.h> |
|||
|
|||
class SwapChainTrampoline : public IDXGISwapChain4 |
|||
{ |
|||
public: |
|||
SwapChainTrampoline(IDXGISwapChain4* swapChain); |
|||
|
|||
HRESULT __stdcall QueryInterface(REFIID riid, void** ppvObject) override; |
|||
|
|||
ULONG __stdcall AddRef(void) override; |
|||
|
|||
ULONG __stdcall Release(void) override; |
|||
|
|||
HRESULT __stdcall SetPrivateData(REFGUID Name, UINT DataSize, const void* pData) override; |
|||
|
|||
HRESULT __stdcall SetPrivateDataInterface(REFGUID Name, const IUnknown* pUnknown) override; |
|||
|
|||
HRESULT __stdcall GetPrivateData(REFGUID Name, UINT* pDataSize, void* pData) override; |
|||
|
|||
HRESULT __stdcall GetParent(REFIID riid, void** ppParent) override; |
|||
|
|||
HRESULT __stdcall GetDevice(REFIID riid, void** ppDevice) override; |
|||
|
|||
HRESULT __stdcall Present(UINT SyncInterval, UINT Flags) override; |
|||
|
|||
HRESULT __stdcall GetBuffer(UINT Buffer, REFIID riid, void** ppSurface) override; |
|||
|
|||
HRESULT __stdcall SetFullscreenState(BOOL Fullscreen, IDXGIOutput* pTarget) override; |
|||
|
|||
HRESULT __stdcall GetFullscreenState(BOOL* pFullscreen, IDXGIOutput** ppTarget) override; |
|||
|
|||
HRESULT __stdcall GetDesc(DXGI_SWAP_CHAIN_DESC* pDesc) override; |
|||
|
|||
HRESULT __stdcall ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) override; |
|||
|
|||
HRESULT __stdcall ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters) override; |
|||
|
|||
HRESULT __stdcall GetContainingOutput(IDXGIOutput** ppOutput) override; |
|||
|
|||
HRESULT __stdcall GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) override; |
|||
|
|||
HRESULT __stdcall GetLastPresentCount(UINT* pLastPresentCount) override; |
|||
|
|||
HRESULT __stdcall GetDesc1(DXGI_SWAP_CHAIN_DESC1* pDesc) override; |
|||
|
|||
HRESULT __stdcall GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) override; |
|||
|
|||
HRESULT __stdcall GetHwnd(HWND* pHwnd) override; |
|||
|
|||
HRESULT __stdcall GetCoreWindow(REFIID refiid, void** ppUnk) override; |
|||
|
|||
HRESULT __stdcall Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters) override; |
|||
|
|||
BOOL __stdcall IsTemporaryMonoSupported(void) override; |
|||
|
|||
HRESULT __stdcall GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput) override; |
|||
|
|||
HRESULT __stdcall SetBackgroundColor(const DXGI_RGBA* pColor) override; |
|||
|
|||
HRESULT __stdcall GetBackgroundColor(DXGI_RGBA* pColor) override; |
|||
|
|||
HRESULT __stdcall SetRotation(DXGI_MODE_ROTATION Rotation) override; |
|||
|
|||
HRESULT __stdcall GetRotation(DXGI_MODE_ROTATION* pRotation) override; |
|||
|
|||
HRESULT __stdcall SetSourceSize(UINT Width, UINT Height) override; |
|||
|
|||
HRESULT __stdcall GetSourceSize(UINT* pWidth, UINT* pHeight) override; |
|||
|
|||
HRESULT __stdcall SetMaximumFrameLatency(UINT MaxLatency) override; |
|||
|
|||
HRESULT __stdcall GetMaximumFrameLatency(UINT* pMaxLatency) override; |
|||
|
|||
HANDLE __stdcall GetFrameLatencyWaitableObject(void) override; |
|||
|
|||
HRESULT __stdcall SetMatrixTransform(const DXGI_MATRIX_3X2_F* pMatrix) override; |
|||
|
|||
HRESULT __stdcall GetMatrixTransform(DXGI_MATRIX_3X2_F* pMatrix) override; |
|||
|
|||
UINT __stdcall GetCurrentBackBufferIndex(void) override; |
|||
|
|||
HRESULT __stdcall CheckColorSpaceSupport(DXGI_COLOR_SPACE_TYPE ColorSpace, UINT* pColorSpaceSupport) override; |
|||
|
|||
HRESULT __stdcall SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) override; |
|||
|
|||
HRESULT __stdcall ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags, const UINT* pCreationNodeMask, IUnknown* const* ppPresentQueue) override; |
|||
|
|||
HRESULT __stdcall SetHDRMetaData(DXGI_HDR_METADATA_TYPE Type, UINT Size, void* pMetaData) override; |
|||
}; |
|||
@ -0,0 +1,227 @@ |
|||
#include "SwapChainTrampoline.h"
|
|||
|
|||
// There can be ever only one swap chain per window, so it's safe to make this a singleton
|
|||
static IDXGISwapChain4* s_SwapChain = nullptr; |
|||
|
|||
typedef HRESULT(__stdcall IDXGISwapChain4::*PFN_QueryInterface)(REFIID riid, void** ppvObject); |
|||
PFN_QueryInterface pfQueryInterface = nullptr; |
|||
|
|||
SwapChainTrampoline::SwapChainTrampoline(IDXGISwapChain4* swapChain) |
|||
{ |
|||
s_SwapChain = swapChain; |
|||
// TODO: copy the original swap chain's vtable (sizeof IDXGISwapChain4), then somehow call the virtual methods in that vtable using the this-pointer from ourselves...
|
|||
|
|||
pfQueryInterface = (PFN_QueryInterface)((intptr_t)swapChain + reinterpret_cast<intptr_t>(&SwapChainTrampoline::QueryInterface)); |
|||
|
|||
// IDEA: we could replace the original swap chain's vtable entries one-by-one with regular function pointers, including a this-pointer argument
|
|||
// Unity will then give us the this-pointer we require, no need to globally store it here
|
|||
// (We might not even require the this-pointer in the long run anyway, since we'll be forwarding to the FG swapchain)
|
|||
// Then forward the call to the original vtable function, reusing that this-pointer where necessary
|
|||
// Only thing we really need to know for sure: the offset in the vtable of each virtual function
|
|||
// This doesn't feel like it would work but try it anyway: https://stackoverflow.com/questions/5590015/detect-the-the-vtable-offset-of-a-specific-virtual-function-using-visual-c/5590181
|
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::QueryInterface(REFIID riid, void** ppvObject) |
|||
{ |
|||
return s_SwapChain->QueryInterface(riid, ppvObject); |
|||
} |
|||
|
|||
ULONG __stdcall SwapChainTrampoline::AddRef(void) |
|||
{ |
|||
return s_SwapChain->AddRef(); |
|||
} |
|||
|
|||
ULONG __stdcall SwapChainTrampoline::Release(void) |
|||
{ |
|||
return s_SwapChain->Release(); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetPrivateData(REFGUID Name, UINT DataSize, const void* pData) |
|||
{ |
|||
return s_SwapChain->SetPrivateData(Name, DataSize, pData); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetPrivateDataInterface(REFGUID Name, const IUnknown* pUnknown) |
|||
{ |
|||
return s_SwapChain->SetPrivateDataInterface(Name, pUnknown); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetPrivateData(REFGUID Name, UINT* pDataSize, void* pData) |
|||
{ |
|||
return s_SwapChain->GetPrivateData(Name, pDataSize, pData); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetParent(REFIID riid, void** ppParent) |
|||
{ |
|||
return s_SwapChain->GetParent(riid, ppParent); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetDevice(REFIID riid, void** ppDevice) |
|||
{ |
|||
return s_SwapChain->GetDevice(riid, ppDevice); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::Present(UINT SyncInterval, UINT Flags) |
|||
{ |
|||
return s_SwapChain->Present(SyncInterval, Flags); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetBuffer(UINT Buffer, REFIID riid, void** ppSurface) |
|||
{ |
|||
return s_SwapChain->GetBuffer(Buffer, riid, ppSurface); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetFullscreenState(BOOL Fullscreen, IDXGIOutput* pTarget) |
|||
{ |
|||
return s_SwapChain->SetFullscreenState(Fullscreen, pTarget); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetFullscreenState(BOOL* pFullscreen, IDXGIOutput** ppTarget) |
|||
{ |
|||
return s_SwapChain->GetFullscreenState(pFullscreen, ppTarget); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetDesc(DXGI_SWAP_CHAIN_DESC* pDesc) |
|||
{ |
|||
return s_SwapChain->GetDesc(pDesc); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::ResizeBuffers(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT NewFormat, UINT SwapChainFlags) |
|||
{ |
|||
return s_SwapChain->ResizeBuffers(BufferCount, Width, Height, NewFormat, SwapChainFlags); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::ResizeTarget(const DXGI_MODE_DESC* pNewTargetParameters) |
|||
{ |
|||
return s_SwapChain->ResizeTarget(pNewTargetParameters); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetContainingOutput(IDXGIOutput** ppOutput) |
|||
{ |
|||
return s_SwapChain->GetContainingOutput(ppOutput); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetFrameStatistics(DXGI_FRAME_STATISTICS* pStats) |
|||
{ |
|||
return s_SwapChain->GetFrameStatistics(pStats); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetLastPresentCount(UINT* pLastPresentCount) |
|||
{ |
|||
return s_SwapChain->GetLastPresentCount(pLastPresentCount); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetDesc1(DXGI_SWAP_CHAIN_DESC1* pDesc) |
|||
{ |
|||
return s_SwapChain->GetDesc1(pDesc); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetFullscreenDesc(DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc) |
|||
{ |
|||
return s_SwapChain->GetFullscreenDesc(pDesc); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetHwnd(HWND* pHwnd) |
|||
{ |
|||
return s_SwapChain->GetHwnd(pHwnd); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetCoreWindow(REFIID refiid, void** ppUnk) |
|||
{ |
|||
return s_SwapChain->GetCoreWindow(refiid, ppUnk); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::Present1(UINT SyncInterval, UINT PresentFlags, const DXGI_PRESENT_PARAMETERS* pPresentParameters) |
|||
{ |
|||
return s_SwapChain->Present1(SyncInterval, PresentFlags, pPresentParameters); |
|||
} |
|||
|
|||
BOOL __stdcall SwapChainTrampoline::IsTemporaryMonoSupported(void) |
|||
{ |
|||
return s_SwapChain->IsTemporaryMonoSupported(); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetRestrictToOutput(IDXGIOutput** ppRestrictToOutput) |
|||
{ |
|||
return s_SwapChain->GetRestrictToOutput(ppRestrictToOutput); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetBackgroundColor(const DXGI_RGBA* pColor) |
|||
{ |
|||
return s_SwapChain->SetBackgroundColor(pColor); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetBackgroundColor(DXGI_RGBA* pColor) |
|||
{ |
|||
return s_SwapChain->GetBackgroundColor(pColor); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetRotation(DXGI_MODE_ROTATION Rotation) |
|||
{ |
|||
return s_SwapChain->SetRotation(Rotation); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetRotation(DXGI_MODE_ROTATION* pRotation) |
|||
{ |
|||
return s_SwapChain->GetRotation(pRotation); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetSourceSize(UINT Width, UINT Height) |
|||
{ |
|||
return s_SwapChain->SetSourceSize(Width, Height); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetSourceSize(UINT* pWidth, UINT* pHeight) |
|||
{ |
|||
return s_SwapChain->GetSourceSize(pWidth, pHeight); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetMaximumFrameLatency(UINT MaxLatency) |
|||
{ |
|||
return s_SwapChain->SetMaximumFrameLatency(MaxLatency); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetMaximumFrameLatency(UINT* pMaxLatency) |
|||
{ |
|||
return s_SwapChain->GetMaximumFrameLatency(pMaxLatency); |
|||
} |
|||
|
|||
HANDLE __stdcall SwapChainTrampoline::GetFrameLatencyWaitableObject(void) |
|||
{ |
|||
return s_SwapChain->GetFrameLatencyWaitableObject(); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetMatrixTransform(const DXGI_MATRIX_3X2_F* pMatrix) |
|||
{ |
|||
return s_SwapChain->SetMatrixTransform(pMatrix); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::GetMatrixTransform(DXGI_MATRIX_3X2_F* pMatrix) |
|||
{ |
|||
return s_SwapChain->GetMatrixTransform(pMatrix); |
|||
} |
|||
|
|||
UINT __stdcall SwapChainTrampoline::GetCurrentBackBufferIndex(void) |
|||
{ |
|||
return s_SwapChain->GetCurrentBackBufferIndex(); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::CheckColorSpaceSupport(DXGI_COLOR_SPACE_TYPE ColorSpace, UINT* pColorSpaceSupport) |
|||
{ |
|||
return s_SwapChain->CheckColorSpaceSupport(ColorSpace, pColorSpaceSupport); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetColorSpace1(DXGI_COLOR_SPACE_TYPE ColorSpace) |
|||
{ |
|||
return s_SwapChain->SetColorSpace1(ColorSpace); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::ResizeBuffers1(UINT BufferCount, UINT Width, UINT Height, DXGI_FORMAT Format, UINT SwapChainFlags, const UINT* pCreationNodeMask, IUnknown* const* ppPresentQueue) |
|||
{ |
|||
return s_SwapChain->ResizeBuffers1(BufferCount, Width, Height, Format, SwapChainFlags, pCreationNodeMask, ppPresentQueue); |
|||
} |
|||
|
|||
HRESULT __stdcall SwapChainTrampoline::SetHDRMetaData(DXGI_HDR_METADATA_TYPE Type, UINT Size, void* pMetaData) |
|||
{ |
|||
return s_SwapChain->SetHDRMetaData(Type, Size, pMetaData); |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue