mirror of
https://github.com/spice2x/spice2x.github.io.git
synced 2026-10-02 08:18:14 -07:00
21e7d24ed3
## Link to GitHub Issue or related Pull Request, if one exists #0 ## Description of change Capturing a frame for the API stream made the game wait for `GetRenderTargetData` in the middle of its present, roughly 1270us per frame at 1080p. A 120Hz cab visibly lost frames for as long as a viewer was connected. The present thread now only issues a `StretchRect` into a render target we own, which is queued rather than waited on, and a pool thread does the readback and the pixel conversion. That takes the present thread cost to 1-4us. Each snapshot is read on the request after the one that took it, so the blit and its transfer have a full frame to land and the read does not stall on the GPU either, at the cost of one frame of stream latency. Only streaming takes this path, and only on a device created with `D3DCREATE_MULTITHREADED`. Screenshots, `capture.get_jpg` and the `THREAD_BAN` models keep the existing inline readback unchanged. Also raises the x264 encoder from `i_threads = 1` to 4, which was holding a 1080p60 stream to 41fps and making a keyframe cost 12.7ms against 6.6ms for an ordinary frame. Capped rather than automatic because this encodes on the same machine it is capturing. ## Testing tested against iidx33, which was the most sensitive to frame drops
292 lines
21 KiB
C++
292 lines
21 KiB
C++
#pragma once
|
|
|
|
#include <array>
|
|
#include <atomic>
|
|
#include <mutex>
|
|
#include <vector>
|
|
|
|
#include <initguid.h>
|
|
#include <d3d9.h>
|
|
|
|
#include "util/logging.h"
|
|
|
|
#include "d3d9_fake_swapchain.h"
|
|
#include "d3d9_swapchain.h"
|
|
|
|
/*
|
|
* Logging Helpers
|
|
*/
|
|
|
|
#if 0
|
|
#define WRAP_VERBOSE log_misc("graphics::d3d9", "{}", __FUNCTION__)
|
|
#define WRAP_VERBOSE_FMT(format, ...) log_misc("graphics::d3d9", format, __VA_ARGS__)
|
|
#else
|
|
#define WRAP_VERBOSE do {} while (0)
|
|
#define WRAP_VERBOSE_FMT(format, ...) do {} while (0)
|
|
#endif
|
|
|
|
#if 0
|
|
#define WRAP_DEBUG log_misc("graphics::d3d9", "{}", __FUNCTION__)
|
|
#define WRAP_DEBUG_FMT(format, ...) log_misc("graphics::d3d9", format, __VA_ARGS__)
|
|
#else
|
|
#define WRAP_DEBUG do {} while (0)
|
|
#define WRAP_DEBUG_FMT(format, ...) do {} while (0)
|
|
#endif
|
|
|
|
// {6DEC0D40-1339-4BDA-A5F2-2231D4010FD1}
|
|
static const GUID IID_WrappedIDirect3DDevice9 = {
|
|
0x6dec0d40, 0x1339, 0x4bda, { 0xa5, 0xf2, 0x22, 0x31, 0xd4, 0x1, 0xf, 0xd1 }
|
|
};
|
|
|
|
// applies the image resize / orientation swap by copying the back buffer through an
|
|
// oversized intermediate surface and back. expects the real (unwrapped) device.
|
|
void SurfaceHook(IDirect3DDevice9 *pReal);
|
|
|
|
struct WrappedIDirect3DDevice9 : IDirect3DDevice9Ex {
|
|
explicit WrappedIDirect3DDevice9(
|
|
HWND hFocusWindow,
|
|
IDirect3DDevice9 *orig,
|
|
UINT gfdm_logical_small_swapchain = 2,
|
|
IDirect3D9 *gfdm_parent_d3d = nullptr,
|
|
const D3DPRESENT_PARAMETERS *gfdm_logical_group_parameters = nullptr)
|
|
: hFocusWindow(hFocusWindow),
|
|
pReal(orig),
|
|
is_d3d9ex(false),
|
|
gfdm_logical_small_swapchain(gfdm_logical_small_swapchain),
|
|
gfdm_parent_d3d(gfdm_parent_d3d) {
|
|
if (this->gfdm_parent_d3d != nullptr) {
|
|
this->gfdm_parent_d3d->AddRef();
|
|
}
|
|
IDirect3DDevice9Ex *device = nullptr;
|
|
|
|
// attempt to upgrade handle
|
|
if (SUCCEEDED(this->QueryInterface(IID_PPV_ARGS(&device))) && device != nullptr) {
|
|
device->Release();
|
|
}
|
|
set_gfdm_logical_group_parameters(gfdm_logical_group_parameters);
|
|
}
|
|
|
|
explicit WrappedIDirect3DDevice9(
|
|
HWND hFocusWindow,
|
|
IDirect3DDevice9Ex *orig,
|
|
UINT gfdm_logical_small_swapchain = 2,
|
|
IDirect3D9 *gfdm_parent_d3d = nullptr,
|
|
const D3DPRESENT_PARAMETERS *gfdm_logical_group_parameters = nullptr)
|
|
: hFocusWindow(hFocusWindow),
|
|
pReal(orig),
|
|
is_d3d9ex(true),
|
|
gfdm_logical_small_swapchain(gfdm_logical_small_swapchain),
|
|
gfdm_parent_d3d(gfdm_parent_d3d) {
|
|
if (this->gfdm_parent_d3d != nullptr) {
|
|
this->gfdm_parent_d3d->AddRef();
|
|
}
|
|
set_gfdm_logical_group_parameters(gfdm_logical_group_parameters);
|
|
}
|
|
|
|
WrappedIDirect3DDevice9(const WrappedIDirect3DDevice9 &) = delete;
|
|
WrappedIDirect3DDevice9 &operator=(const WrappedIDirect3DDevice9 &) = delete;
|
|
|
|
virtual ~WrappedIDirect3DDevice9() {
|
|
if (gfdm_parent_d3d != nullptr) {
|
|
gfdm_parent_d3d->Release();
|
|
}
|
|
}
|
|
|
|
#pragma region IUnknown
|
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObj) override;
|
|
virtual ULONG STDMETHODCALLTYPE AddRef() override;
|
|
virtual ULONG STDMETHODCALLTYPE Release() override;
|
|
#pragma endregion
|
|
|
|
#pragma region IDirect3DDevice9
|
|
virtual HRESULT STDMETHODCALLTYPE TestCooperativeLevel() override;
|
|
virtual UINT STDMETHODCALLTYPE GetAvailableTextureMem() override;
|
|
virtual HRESULT STDMETHODCALLTYPE EvictManagedResources() override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetDirect3D(IDirect3D9 **ppD3D9) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetDeviceCaps(D3DCAPS9 *pCaps) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE *pMode) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetCursorProperties(UINT XHotSpot, UINT YHotSpot, IDirect3DSurface9 *pCursorBitmap) override;
|
|
virtual void STDMETHODCALLTYPE SetCursorPosition(int X, int Y, DWORD Flags) override;
|
|
virtual BOOL STDMETHODCALLTYPE ShowCursor(BOOL bShow) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChain(D3DPRESENT_PARAMETERS *pPresentationParameters, IDirect3DSwapChain9 **ppSwapChain) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9 **ppSwapChain) override;
|
|
virtual UINT STDMETHODCALLTYPE GetNumberOfSwapChains() override;
|
|
virtual HRESULT STDMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS *pPresentationParameters) override;
|
|
virtual HRESULT STDMETHODCALLTYPE Present(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetBackBuffer(UINT iSwapChain, UINT iBackBuffer, D3DBACKBUFFER_TYPE Type, IDirect3DSurface9 **ppBackBuffer) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS *pRasterStatus) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetDialogBoxMode(BOOL bEnableDialogs) override;
|
|
virtual void STDMETHODCALLTYPE SetGammaRamp(UINT iSwapChain, DWORD Flags, const D3DGAMMARAMP *pRamp) override;
|
|
virtual void STDMETHODCALLTYPE GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP *pRamp) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateTexture(UINT Width, UINT Height, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DTexture9 **ppTexture, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateVolumeTexture(UINT Width, UINT Height, UINT Depth, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DVolumeTexture9 **ppVolumeTexture, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateCubeTexture(UINT EdgeLength, UINT Levels, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DCubeTexture9 **ppCubeTexture, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateVertexBuffer(UINT Length, DWORD Usage, DWORD FVF, D3DPOOL Pool, IDirect3DVertexBuffer9 **ppVertexBuffer, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, D3DPOOL Pool, IDirect3DIndexBuffer9 **ppIndexBuffer, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateRenderTarget(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE UpdateSurface(IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect, IDirect3DSurface9 *pDestinationSurface, const POINT *pDestPoint) override;
|
|
virtual HRESULT STDMETHODCALLTYPE UpdateTexture(IDirect3DBaseTexture9 *pSourceTexture, IDirect3DBaseTexture9 *pDestinationTexture) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetRenderTargetData(IDirect3DSurface9 *pRenderTarget, IDirect3DSurface9 *pDestSurface) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9 *pDestSurface) override;
|
|
virtual HRESULT STDMETHODCALLTYPE StretchRect(IDirect3DSurface9 *pSourceSurface, const RECT *pSourceRect, IDirect3DSurface9 *pDestSurface, const RECT *pDestRect, D3DTEXTUREFILTERTYPE Filter) override;
|
|
virtual HRESULT STDMETHODCALLTYPE ColorFill(IDirect3DSurface9 *pSurface, const RECT *pRect, D3DCOLOR color) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurface(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9 *pRenderTarget) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetRenderTarget(DWORD RenderTargetIndex, IDirect3DSurface9 **ppRenderTarget) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetDepthStencilSurface(IDirect3DSurface9 *pNewZStencil) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface9 **ppZStencilSurface) override;
|
|
virtual HRESULT STDMETHODCALLTYPE BeginScene() override;
|
|
virtual HRESULT STDMETHODCALLTYPE EndScene() override;
|
|
virtual HRESULT STDMETHODCALLTYPE Clear(DWORD Count, const D3DRECT *pRects, DWORD Flags, D3DCOLOR Color, float Z, DWORD Stencil) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX *pMatrix) override;
|
|
virtual HRESULT STDMETHODCALLTYPE MultiplyTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX *pMatrix) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetViewport(const D3DVIEWPORT9 *pViewport) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetViewport(D3DVIEWPORT9 *pViewport) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetMaterial(const D3DMATERIAL9 *pMaterial) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetMaterial(D3DMATERIAL9 *pMaterial) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, const D3DLIGHT9 *pLight) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetLight(DWORD Index, D3DLIGHT9 *pLight) override;
|
|
virtual HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetLightEnable(DWORD Index, BOOL *pEnable) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetClipPlane(DWORD Index, const float *pPlane) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetClipPlane(DWORD Index, float *pPlane) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetRenderState(D3DRENDERSTATETYPE State, DWORD *pValue) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateStateBlock(D3DSTATEBLOCKTYPE Type, IDirect3DStateBlock9 **ppSB) override;
|
|
virtual HRESULT STDMETHODCALLTYPE BeginStateBlock() override;
|
|
virtual HRESULT STDMETHODCALLTYPE EndStateBlock(IDirect3DStateBlock9 **ppSB) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetClipStatus(const D3DCLIPSTATUS9 *pClipStatus) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetClipStatus(D3DCLIPSTATUS9 *pClipStatus) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetTexture(DWORD Stage, IDirect3DBaseTexture9 **ppTexture) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetTexture(DWORD Stage, IDirect3DBaseTexture9 *pTexture) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD *pValue) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD *pValue) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value) override;
|
|
virtual HRESULT STDMETHODCALLTYPE ValidateDevice(DWORD *pNumPasses) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetPaletteEntries(UINT PaletteNumber, const PALETTEENTRY *pEntries) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY *pEntries) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetCurrentTexturePalette(UINT PaletteNumber) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetCurrentTexturePalette(UINT *PaletteNumber) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetScissorRect(const RECT *pRect) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetScissorRect(RECT *pRect) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetSoftwareVertexProcessing(BOOL bSoftware) override;
|
|
virtual BOOL STDMETHODCALLTYPE GetSoftwareVertexProcessing() override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetNPatchMode(float nSegments) override;
|
|
virtual float STDMETHODCALLTYPE GetNPatchMode() override;
|
|
virtual HRESULT STDMETHODCALLTYPE DrawPrimitive(D3DPRIMITIVETYPE PrimitiveType, UINT StartVertex, UINT PrimitiveCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE DrawIndexedPrimitive(D3DPRIMITIVETYPE PrimitiveType, INT BaseVertexIndex, UINT MinVertexIndex, UINT NumVertices, UINT startIndex, UINT primCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE DrawPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT PrimitiveCount, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) override;
|
|
virtual HRESULT STDMETHODCALLTYPE DrawIndexedPrimitiveUP(D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, UINT PrimitiveCount, const void *pIndexData, D3DFORMAT IndexDataFormat, const void *pVertexStreamZeroData, UINT VertexStreamZeroStride) override;
|
|
virtual HRESULT STDMETHODCALLTYPE ProcessVertices(UINT SrcStartIndex, UINT DestIndex, UINT VertexCount, IDirect3DVertexBuffer9 *pDestBuffer, IDirect3DVertexDeclaration9 *pVertexDecl, DWORD Flags) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateVertexDeclaration(const D3DVERTEXELEMENT9 *pVertexElements, IDirect3DVertexDeclaration9 **ppDecl) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetVertexDeclaration(IDirect3DVertexDeclaration9 *pDecl) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetVertexDeclaration(IDirect3DVertexDeclaration9 **ppDecl) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetFVF(DWORD FVF) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetFVF(DWORD *pFVF) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateVertexShader(const DWORD *pFunction, IDirect3DVertexShader9 **ppShader) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetVertexShader(IDirect3DVertexShader9 *pShader) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetVertexShader(IDirect3DVertexShader9 **ppShader) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetVertexShaderConstantF(UINT StartRegister, const float *pConstantData, UINT Vector4fCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetVertexShaderConstantF(UINT StartRegister, float *pConstantData, UINT Vector4fCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetVertexShaderConstantI(UINT StartRegister, const int *pConstantData, UINT Vector4iCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetVertexShaderConstantI(UINT StartRegister, int *pConstantData, UINT Vector4iCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetVertexShaderConstantB(UINT StartRegister, const BOOL *pConstantData, UINT BoolCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetVertexShaderConstantB(UINT StartRegister, BOOL *pConstantData, UINT BoolCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9 *pStreamData, UINT OffsetInBytes, UINT Stride) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetStreamSource(UINT StreamNumber, IDirect3DVertexBuffer9 **ppStreamData, UINT *OffsetInBytes, UINT *pStride) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetStreamSourceFreq(UINT StreamNumber, UINT Divider) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetStreamSourceFreq(UINT StreamNumber, UINT *Divider) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer9 *pIndexData) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetIndices(IDirect3DIndexBuffer9 **ppIndexData) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreatePixelShader(const DWORD *pFunction, IDirect3DPixelShader9 **ppShader) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetPixelShader(IDirect3DPixelShader9 *pShader) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetPixelShader(IDirect3DPixelShader9 **ppShader) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetPixelShaderConstantF(UINT StartRegister, const float *pConstantData, UINT Vector4fCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetPixelShaderConstantF(UINT StartRegister, float *pConstantData, UINT Vector4fCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetPixelShaderConstantI(UINT StartRegister, const int *pConstantData, UINT Vector4iCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetPixelShaderConstantI(UINT StartRegister, int *pConstantData, UINT Vector4iCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetPixelShaderConstantB(UINT StartRegister, const BOOL *pConstantData, UINT BoolCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetPixelShaderConstantB(UINT StartRegister, BOOL *pConstantData, UINT BoolCount) override;
|
|
virtual HRESULT STDMETHODCALLTYPE DrawRectPatch(UINT Handle, const float *pNumSegs, const D3DRECTPATCH_INFO *pRectPatchInfo) override;
|
|
virtual HRESULT STDMETHODCALLTYPE DrawTriPatch(UINT Handle, const float *pNumSegs, const D3DTRIPATCH_INFO *pTriPatchInfo) override;
|
|
virtual HRESULT STDMETHODCALLTYPE DeletePatch(UINT Handle) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9 **ppQuery) override;
|
|
#pragma endregion
|
|
|
|
#pragma region IDirect3DDevice9Ex
|
|
virtual HRESULT STDMETHODCALLTYPE SetConvolutionMonoKernel(UINT width, UINT height, float *rows, float *columns) override;
|
|
virtual HRESULT STDMETHODCALLTYPE ComposeRects(IDirect3DSurface9 *pSrc, IDirect3DSurface9 *pDst, IDirect3DVertexBuffer9 *pSrcRectDescs, UINT NumRects, IDirect3DVertexBuffer9 *pDstRectDescs, D3DCOMPOSERECTSOP Operation, int Xoffset, int Yoffset) override;
|
|
virtual HRESULT STDMETHODCALLTYPE PresentEx(const RECT *pSourceRect, const RECT *pDestRect, HWND hDestWindowOverride, const RGNDATA *pDirtyRegion, DWORD dwFlags) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(INT *pPriority) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(INT Priority) override;
|
|
virtual HRESULT STDMETHODCALLTYPE WaitForVBlank(UINT iSwapChain) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CheckResourceResidency(IDirect3DResource9 **pResourceArray, UINT32 NumResources) override;
|
|
virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT *pMaxLatency) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CheckDeviceState(HWND hDestinationWindow) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateRenderTargetEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Lockable, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DPOOL Pool, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) override;
|
|
virtual HRESULT STDMETHODCALLTYPE CreateDepthStencilSurfaceEx(UINT Width, UINT Height, D3DFORMAT Format, D3DMULTISAMPLE_TYPE MultiSample, DWORD MultisampleQuality, BOOL Discard, IDirect3DSurface9 **ppSurface, HANDLE *pSharedHandle, DWORD Usage) override;
|
|
virtual HRESULT STDMETHODCALLTYPE ResetEx(D3DPRESENT_PARAMETERS *pPresentationParameters, D3DDISPLAYMODEEX *pFullscreenDisplayMode) override;
|
|
virtual HRESULT STDMETHODCALLTYPE GetDisplayModeEx(UINT iSwapChain, D3DDISPLAYMODEEX *pMode, D3DDISPLAYROTATION *pRotation) override;
|
|
#pragma endregion
|
|
|
|
// logical screens the game draws, and the swap chain each one lives on
|
|
void get_screenshot_screens(std::vector<int> &screens) const;
|
|
HRESULT get_screenshot_swap_chain(UINT iSwapChain, IDirect3DSwapChain9 **ppSwapChain);
|
|
|
|
bool is_gfdm_two_head_exclusive() const;
|
|
bool is_gfdm_logical_small_swapchain(UINT swapchain) const;
|
|
bool is_gfdm_logical_side_swapchain(UINT swapchain) const;
|
|
size_t gfdm_hidden_side_swapchain_slot(UINT swapchain) const;
|
|
void set_gfdm_logical_group_parameters(
|
|
const D3DPRESENT_PARAMETERS *presentation_parameters);
|
|
FakeIDirect3DSwapChain9 *ensure_gfdm_hidden_side_swapchain(UINT iSwapChain);
|
|
void release_gfdm_hidden_side_swapchains();
|
|
|
|
enum class GfdmPresentModeRecoveryResult {
|
|
NotAttempted,
|
|
ReadyToRetry,
|
|
Failed,
|
|
};
|
|
void gfdm_disarm_present_mode_recovery();
|
|
void gfdm_arm_present_mode_recovery(
|
|
const D3DPRESENT_PARAMETERS *native_presentation_parameters,
|
|
const D3DDISPLAYMODEEX *native_fullscreen_display_modes);
|
|
GfdmPresentModeRecoveryResult gfdm_recover_present_mode_change(
|
|
HRESULT *failure_result);
|
|
|
|
HWND const hFocusWindow;
|
|
IDirect3DDevice9 *pReal;
|
|
bool is_d3d9ex = false;
|
|
|
|
// set from the creation flags; without it the runtime does no locking of its own, so
|
|
// nothing but the present thread may touch the device
|
|
bool device_multithreaded = false;
|
|
|
|
std::atomic_ulong refs = 1;
|
|
|
|
WrappedIDirect3DSwapChain9 *main_swapchain = nullptr;
|
|
WrappedIDirect3DSwapChain9 *implicit_sub_swapchain = nullptr;
|
|
WrappedIDirect3DSwapChain9 *sub_swapchain[3] = { nullptr, nullptr, nullptr };
|
|
FakeIDirect3DSwapChain9 *fake_sub_swapchain[3] = { nullptr, nullptr, nullptr };
|
|
|
|
UINT gfdm_logical_small_swapchain = 2;
|
|
std::array<D3DPRESENT_PARAMETERS, 4> gfdm_logical_group_parameters {};
|
|
bool gfdm_logical_group_parameters_valid = false;
|
|
IDirect3D9 *gfdm_parent_d3d = nullptr;
|
|
|
|
std::mutex gfdm_recovery_mutex;
|
|
std::array<D3DPRESENT_PARAMETERS, 2> gfdm_recovery_parameters {};
|
|
std::array<D3DDISPLAYMODEEX, 2> gfdm_recovery_modes {};
|
|
bool gfdm_recovery_armed = false;
|
|
std::atomic_bool gfdm_recovery_consumed {false};
|
|
const DWORD gfdm_device_creation_thread_id = GetCurrentThreadId();
|
|
|
|
IDirect3DVertexShader9 *vertex_shader = nullptr;
|
|
};
|