1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2024-12-14 18:23:52 +01:00
dxvk/src/d3d9/d3d9_device.h

1153 lines
37 KiB
C
Raw Normal View History

#pragma once
#include "../dxvk/dxvk_device.h"
#include "../dxvk/dxvk_cs.h"
#include "d3d9_include.h"
#include "d3d9_cursor.h"
#include "d3d9_format.h"
#include "d3d9_multithread.h"
#include "d3d9_adapter.h"
#include "d3d9_constant_set.h"
#include "d3d9_state.h"
#include "d3d9_options.h"
#include "../dxso/dxso_module.h"
#include "../dxso/dxso_util.h"
#include "../dxso/dxso_options.h"
#include "../dxso/dxso_modinfo.h"
#include "d3d9_sampler.h"
#include "d3d9_fixed_function.h"
#include "d3d9_swvp_emu.h"
#include "d3d9_shader_permutations.h"
#include <vector>
#include <type_traits>
#include <unordered_map>
namespace dxvk {
class D3D9InterfaceEx;
class D3D9SwapChainEx;
class D3D9CommonTexture;
class D3D9CommonBuffer;
class D3D9CommonShader;
class D3D9ShaderModuleSet;
class D3D9Initializer;
class D3D9Query;
class D3D9StateBlock;
class D3D9FormatHelper;
enum class D3D9DeviceFlag : uint32_t {
DirtyFramebuffer,
DirtyClipPlanes,
DirtyDepthStencilState,
DirtyBlendState,
DirtyRasterizerState,
DirtyAlphaTestState,
DirtyInputLayout,
DirtyViewportScissor,
DirtyMultiSampleState,
DirtyFogState,
DirtyFogColor,
DirtyFogDensity,
DirtyFogScale,
DirtyFogEnd,
DirtyFFVertexData,
DirtyFFVertexBlend,
DirtyFFVertexShader,
DirtyFFPixelShader,
DirtyFFViewport,
DirtyFFPixelData,
DirtyProgVertexShader,
DirtySharedPixelShaderData,
UpDirtiedVertices,
UpDirtiedIndices,
ValidSampleMask,
DirtyDepthBounds,
DirtyPointScale,
};
using D3D9DeviceFlags = Flags<D3D9DeviceFlag>;
struct D3D9DrawInfo {
uint32_t vertexCount;
uint32_t instanceCount;
};
struct D3D9SamplerPair {
Rc<DxvkSampler> color;
Rc<DxvkSampler> depth;
};
struct D3D9UPBufferSlice {
DxvkBufferSlice slice = {};
void* mapPtr = nullptr;
};
class D3D9DeviceEx final : public ComObjectClamp<IDirect3DDevice9Ex> {
constexpr static uint32_t DefaultFrameLatency = 3;
constexpr static uint32_t MaxFrameLatency = 20;
constexpr static uint32_t MinFlushIntervalUs = 750;
constexpr static uint32_t IncFlushIntervalUs = 250;
constexpr static uint32_t MaxPendingSubmits = 6;
constexpr static uint32_t NullStreamIdx = caps::MaxStreams;
friend class D3D9SwapChainEx;
public:
D3D9DeviceEx(
D3D9InterfaceEx* pParent,
D3D9Adapter* pAdapter,
D3DDEVTYPE DeviceType,
HWND hFocusWindow,
DWORD BehaviorFlags,
Rc<DxvkDevice> dxvkDevice);
~D3D9DeviceEx();
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject);
HRESULT STDMETHODCALLTYPE TestCooperativeLevel();
UINT STDMETHODCALLTYPE GetAvailableTextureMem();
HRESULT STDMETHODCALLTYPE EvictManagedResources();
HRESULT STDMETHODCALLTYPE GetDirect3D(IDirect3D9** ppD3D9);
HRESULT STDMETHODCALLTYPE GetDeviceCaps(D3DCAPS9* pCaps);
HRESULT STDMETHODCALLTYPE GetDisplayMode(UINT iSwapChain, D3DDISPLAYMODE* pMode);
HRESULT STDMETHODCALLTYPE GetCreationParameters(D3DDEVICE_CREATION_PARAMETERS *pParameters);
HRESULT STDMETHODCALLTYPE SetCursorProperties(
UINT XHotSpot,
UINT YHotSpot,
IDirect3DSurface9* pCursorBitmap);
void STDMETHODCALLTYPE SetCursorPosition(int X, int Y, DWORD Flags);
BOOL STDMETHODCALLTYPE ShowCursor(BOOL bShow);
HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChain(
D3DPRESENT_PARAMETERS* pPresentationParameters,
IDirect3DSwapChain9** ppSwapChain);
HRESULT STDMETHODCALLTYPE GetSwapChain(UINT iSwapChain, IDirect3DSwapChain9** pSwapChain);
UINT STDMETHODCALLTYPE GetNumberOfSwapChains();
HRESULT STDMETHODCALLTYPE Reset(D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT STDMETHODCALLTYPE Present(
const RECT* pSourceRect,
const RECT* pDestRect, HWND hDestWindowOverride,
const RGNDATA* pDirtyRegion);
HRESULT STDMETHODCALLTYPE GetBackBuffer(
UINT iSwapChain,
UINT iBackBuffer,
D3DBACKBUFFER_TYPE Type,
IDirect3DSurface9** ppBackBuffer);
HRESULT STDMETHODCALLTYPE GetRasterStatus(UINT iSwapChain, D3DRASTER_STATUS* pRasterStatus);
HRESULT STDMETHODCALLTYPE SetDialogBoxMode(BOOL bEnableDialogs);
void STDMETHODCALLTYPE SetGammaRamp(
UINT iSwapChain,
DWORD Flags,
const D3DGAMMARAMP* pRamp);
void STDMETHODCALLTYPE GetGammaRamp(UINT iSwapChain, D3DGAMMARAMP* pRamp);
HRESULT STDMETHODCALLTYPE CreateTexture(
UINT Width,
UINT Height,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DTexture9** ppTexture,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE CreateVolumeTexture(
UINT Width,
UINT Height,
UINT Depth,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DVolumeTexture9** ppVolumeTexture,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE CreateCubeTexture(
UINT EdgeLength,
UINT Levels,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DCubeTexture9** ppCubeTexture,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE CreateVertexBuffer(
UINT Length,
DWORD Usage,
DWORD FVF,
D3DPOOL Pool,
IDirect3DVertexBuffer9** ppVertexBuffer,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE CreateIndexBuffer(
UINT Length,
DWORD Usage,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DIndexBuffer9** ppIndexBuffer,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE CreateRenderTarget(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DMULTISAMPLE_TYPE MultiSample,
DWORD MultisampleQuality,
BOOL Lockable,
IDirect3DSurface9** ppSurface,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE CreateDepthStencilSurface(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DMULTISAMPLE_TYPE MultiSample,
DWORD MultisampleQuality,
BOOL Discard,
IDirect3DSurface9** ppSurface,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE UpdateSurface(
IDirect3DSurface9* pSourceSurface,
const RECT* pSourceRect,
IDirect3DSurface9* pDestinationSurface,
const POINT* pDestPoint);
HRESULT STDMETHODCALLTYPE UpdateTexture(
IDirect3DBaseTexture9* pSourceTexture,
IDirect3DBaseTexture9* pDestinationTexture);
HRESULT STDMETHODCALLTYPE GetRenderTargetData(
IDirect3DSurface9* pRenderTarget,
IDirect3DSurface9* pDestSurface);
HRESULT STDMETHODCALLTYPE GetFrontBufferData(UINT iSwapChain, IDirect3DSurface9* pDestSurface);
HRESULT STDMETHODCALLTYPE StretchRect(
IDirect3DSurface9* pSourceSurface,
const RECT* pSourceRect,
IDirect3DSurface9* pDestSurface,
const RECT* pDestRect,
D3DTEXTUREFILTERTYPE Filter);
HRESULT STDMETHODCALLTYPE ColorFill(
IDirect3DSurface9* pSurface,
const RECT* pRect,
D3DCOLOR Color);
HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurface(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DSurface9** ppSurface,
HANDLE* pSharedHandle);
HRESULT STDMETHODCALLTYPE SetRenderTarget(
DWORD RenderTargetIndex,
IDirect3DSurface9* pRenderTarget);
HRESULT STDMETHODCALLTYPE GetRenderTarget(
DWORD RenderTargetIndex,
IDirect3DSurface9** ppRenderTarget);
HRESULT STDMETHODCALLTYPE SetDepthStencilSurface(IDirect3DSurface9* pNewZStencil);
HRESULT STDMETHODCALLTYPE GetDepthStencilSurface(IDirect3DSurface9** ppZStencilSurface);
HRESULT STDMETHODCALLTYPE BeginScene();
HRESULT STDMETHODCALLTYPE EndScene();
HRESULT STDMETHODCALLTYPE Clear(
DWORD Count,
const D3DRECT* pRects,
DWORD Flags,
D3DCOLOR Color,
float Z,
DWORD Stencil);
HRESULT STDMETHODCALLTYPE SetTransform(D3DTRANSFORMSTATETYPE State, const D3DMATRIX* pMatrix);
HRESULT STDMETHODCALLTYPE GetTransform(D3DTRANSFORMSTATETYPE State, D3DMATRIX* pMatrix);
HRESULT STDMETHODCALLTYPE MultiplyTransform(D3DTRANSFORMSTATETYPE TransformState, const D3DMATRIX* pMatrix);
HRESULT STDMETHODCALLTYPE SetViewport(const D3DVIEWPORT9* pViewport);
HRESULT STDMETHODCALLTYPE GetViewport(D3DVIEWPORT9* pViewport);
HRESULT STDMETHODCALLTYPE SetMaterial(const D3DMATERIAL9* pMaterial);
HRESULT STDMETHODCALLTYPE GetMaterial(D3DMATERIAL9* pMaterial);
HRESULT STDMETHODCALLTYPE SetLight(DWORD Index, const D3DLIGHT9* pLight);
HRESULT STDMETHODCALLTYPE GetLight(DWORD Index, D3DLIGHT9* pLight);
HRESULT STDMETHODCALLTYPE LightEnable(DWORD Index, BOOL Enable);
HRESULT STDMETHODCALLTYPE GetLightEnable(DWORD Index, BOOL* pEnable);
HRESULT STDMETHODCALLTYPE SetClipPlane(DWORD Index, const float* pPlane);
HRESULT STDMETHODCALLTYPE GetClipPlane(DWORD Index, float* pPlane);
HRESULT STDMETHODCALLTYPE SetRenderState(D3DRENDERSTATETYPE State, DWORD Value);
HRESULT STDMETHODCALLTYPE GetRenderState(D3DRENDERSTATETYPE State, DWORD* pValue);
HRESULT STDMETHODCALLTYPE CreateStateBlock(
D3DSTATEBLOCKTYPE Type,
IDirect3DStateBlock9** ppSB);
HRESULT STDMETHODCALLTYPE BeginStateBlock();
HRESULT STDMETHODCALLTYPE EndStateBlock(IDirect3DStateBlock9** ppSB);
HRESULT STDMETHODCALLTYPE SetClipStatus(const D3DCLIPSTATUS9* pClipStatus);
HRESULT STDMETHODCALLTYPE GetClipStatus(D3DCLIPSTATUS9* pClipStatus);
HRESULT STDMETHODCALLTYPE GetTexture(DWORD Stage, IDirect3DBaseTexture9** ppTexture);
HRESULT STDMETHODCALLTYPE SetTexture(DWORD Stage, IDirect3DBaseTexture9* pTexture);
HRESULT STDMETHODCALLTYPE GetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD* pValue);
HRESULT STDMETHODCALLTYPE SetTextureStageState(
DWORD Stage,
D3DTEXTURESTAGESTATETYPE Type,
DWORD Value);
HRESULT STDMETHODCALLTYPE GetSamplerState(
DWORD Sampler,
D3DSAMPLERSTATETYPE Type,
DWORD* pValue);
HRESULT STDMETHODCALLTYPE SetSamplerState(
DWORD Sampler,
D3DSAMPLERSTATETYPE Type,
DWORD Value);
HRESULT STDMETHODCALLTYPE ValidateDevice(DWORD* pNumPasses);
HRESULT STDMETHODCALLTYPE SetPaletteEntries(UINT PaletteNumber, const PALETTEENTRY* pEntries);
HRESULT STDMETHODCALLTYPE GetPaletteEntries(UINT PaletteNumber, PALETTEENTRY* pEntries);
HRESULT STDMETHODCALLTYPE SetCurrentTexturePalette(UINT PaletteNumber);
HRESULT STDMETHODCALLTYPE GetCurrentTexturePalette(UINT *PaletteNumber);
HRESULT STDMETHODCALLTYPE SetScissorRect(const RECT* pRect);
HRESULT STDMETHODCALLTYPE GetScissorRect(RECT* pRect);
HRESULT STDMETHODCALLTYPE SetSoftwareVertexProcessing(BOOL bSoftware);
BOOL STDMETHODCALLTYPE GetSoftwareVertexProcessing();
HRESULT STDMETHODCALLTYPE SetNPatchMode(float nSegments);
float STDMETHODCALLTYPE GetNPatchMode();
HRESULT STDMETHODCALLTYPE DrawPrimitive(
D3DPRIMITIVETYPE PrimitiveType,
UINT StartVertex,
UINT PrimitiveCount);
HRESULT STDMETHODCALLTYPE DrawIndexedPrimitive(
D3DPRIMITIVETYPE PrimitiveType,
INT BaseVertexIndex,
UINT MinVertexIndex,
UINT NumVertices,
UINT StartIndex,
UINT PrimitiveCount);
HRESULT STDMETHODCALLTYPE DrawPrimitiveUP(
D3DPRIMITIVETYPE PrimitiveType,
UINT PrimitiveCount,
const void* pVertexStreamZeroData,
UINT VertexStreamZeroStride);
HRESULT STDMETHODCALLTYPE DrawIndexedPrimitiveUP(
D3DPRIMITIVETYPE PrimitiveType,
UINT MinVertexIndex,
UINT NumVertices,
UINT PrimitiveCount,
const void* pIndexData,
D3DFORMAT IndexDataFormat,
const void* pVertexStreamZeroData,
UINT VertexStreamZeroStride);
HRESULT STDMETHODCALLTYPE ProcessVertices(
UINT SrcStartIndex,
UINT DestIndex,
UINT VertexCount,
IDirect3DVertexBuffer9* pDestBuffer,
IDirect3DVertexDeclaration9* pVertexDecl,
DWORD Flags);
HRESULT STDMETHODCALLTYPE CreateVertexDeclaration(
const D3DVERTEXELEMENT9* pVertexElements,
IDirect3DVertexDeclaration9** ppDecl);
HRESULT STDMETHODCALLTYPE SetVertexDeclaration(IDirect3DVertexDeclaration9* pDecl);
HRESULT STDMETHODCALLTYPE GetVertexDeclaration(IDirect3DVertexDeclaration9** ppDecl);
HRESULT STDMETHODCALLTYPE SetFVF(DWORD FVF);
HRESULT STDMETHODCALLTYPE GetFVF(DWORD* pFVF);
HRESULT STDMETHODCALLTYPE CreateVertexShader(
const DWORD* pFunction,
IDirect3DVertexShader9** ppShader);
HRESULT STDMETHODCALLTYPE SetVertexShader(IDirect3DVertexShader9* pShader);
HRESULT STDMETHODCALLTYPE GetVertexShader(IDirect3DVertexShader9** ppShader);
HRESULT STDMETHODCALLTYPE SetVertexShaderConstantF(
UINT StartRegister,
const float* pConstantData,
UINT Vector4fCount);
HRESULT STDMETHODCALLTYPE GetVertexShaderConstantF(
UINT StartRegister,
float* pConstantData,
UINT Vector4fCount);
HRESULT STDMETHODCALLTYPE SetVertexShaderConstantI(
UINT StartRegister,
const int* pConstantData,
UINT Vector4iCount);
HRESULT STDMETHODCALLTYPE GetVertexShaderConstantI(
UINT StartRegister,
int* pConstantData,
UINT Vector4iCount);
HRESULT STDMETHODCALLTYPE SetVertexShaderConstantB(
UINT StartRegister,
const BOOL* pConstantData,
UINT BoolCount);
HRESULT STDMETHODCALLTYPE GetVertexShaderConstantB(
UINT StartRegister,
BOOL* pConstantData,
UINT BoolCount);
HRESULT STDMETHODCALLTYPE SetStreamSource(
UINT StreamNumber,
IDirect3DVertexBuffer9* pStreamData,
UINT OffsetInBytes,
UINT Stride);
HRESULT STDMETHODCALLTYPE GetStreamSource(
UINT StreamNumber,
IDirect3DVertexBuffer9** ppStreamData,
UINT* pOffsetInBytes,
UINT* pStride);
HRESULT STDMETHODCALLTYPE SetStreamSourceFreq(UINT StreamNumber, UINT Setting);
HRESULT STDMETHODCALLTYPE GetStreamSourceFreq(UINT StreamNumber, UINT* pSetting);
HRESULT STDMETHODCALLTYPE SetIndices(IDirect3DIndexBuffer9* pIndexData);
HRESULT STDMETHODCALLTYPE GetIndices(IDirect3DIndexBuffer9** ppIndexData);
HRESULT STDMETHODCALLTYPE CreatePixelShader(
const DWORD* pFunction,
IDirect3DPixelShader9** ppShader);
HRESULT STDMETHODCALLTYPE SetPixelShader(IDirect3DPixelShader9* pShader);
HRESULT STDMETHODCALLTYPE GetPixelShader(IDirect3DPixelShader9** ppShader);
HRESULT STDMETHODCALLTYPE SetPixelShaderConstantF(
UINT StartRegister,
const float* pConstantData,
UINT Vector4fCount);
HRESULT STDMETHODCALLTYPE GetPixelShaderConstantF(
UINT StartRegister,
float* pConstantData,
UINT Vector4fCount);
HRESULT STDMETHODCALLTYPE SetPixelShaderConstantI(
UINT StartRegister,
const int* pConstantData,
UINT Vector4iCount);
HRESULT STDMETHODCALLTYPE GetPixelShaderConstantI(
UINT StartRegister,
int* pConstantData,
UINT Vector4iCount);
HRESULT STDMETHODCALLTYPE SetPixelShaderConstantB(
UINT StartRegister,
const BOOL* pConstantData,
UINT BoolCount);
HRESULT STDMETHODCALLTYPE GetPixelShaderConstantB(
UINT StartRegister,
BOOL* pConstantData,
UINT BoolCount);
HRESULT STDMETHODCALLTYPE DrawRectPatch(
UINT Handle,
const float* pNumSegs,
const D3DRECTPATCH_INFO* pRectPatchInfo);
HRESULT STDMETHODCALLTYPE DrawTriPatch(
UINT Handle,
const float* pNumSegs,
const D3DTRIPATCH_INFO* pTriPatchInfo);
HRESULT STDMETHODCALLTYPE DeletePatch(UINT Handle);
HRESULT STDMETHODCALLTYPE CreateQuery(D3DQUERYTYPE Type, IDirect3DQuery9** ppQuery);
// Ex Methods
HRESULT STDMETHODCALLTYPE SetConvolutionMonoKernel(
UINT width,
UINT height,
float* rows,
float* columns);
HRESULT STDMETHODCALLTYPE ComposeRects(
IDirect3DSurface9* pSrc,
IDirect3DSurface9* pDst,
IDirect3DVertexBuffer9* pSrcRectDescs,
UINT NumRects,
IDirect3DVertexBuffer9* pDstRectDescs,
D3DCOMPOSERECTSOP Operation,
int Xoffset,
int Yoffset);
HRESULT STDMETHODCALLTYPE GetGPUThreadPriority(INT* pPriority);
HRESULT STDMETHODCALLTYPE SetGPUThreadPriority(INT Priority);
HRESULT STDMETHODCALLTYPE WaitForVBlank(UINT iSwapChain);
HRESULT STDMETHODCALLTYPE CheckResourceResidency(IDirect3DResource9** pResourceArray, UINT32 NumResources);
HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency(UINT MaxLatency);
HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency(UINT* pMaxLatency);
HRESULT STDMETHODCALLTYPE CheckDeviceState(HWND hDestinationWindow);
HRESULT STDMETHODCALLTYPE PresentEx(
const RECT* pSourceRect,
const RECT* pDestRect,
HWND hDestWindowOverride,
const RGNDATA* pDirtyRegion,
DWORD dwFlags);
HRESULT STDMETHODCALLTYPE CreateRenderTargetEx(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DMULTISAMPLE_TYPE MultiSample,
DWORD MultisampleQuality,
BOOL Lockable,
IDirect3DSurface9** ppSurface,
HANDLE* pSharedHandle,
DWORD Usage);
HRESULT STDMETHODCALLTYPE CreateOffscreenPlainSurfaceEx(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DPOOL Pool,
IDirect3DSurface9** ppSurface,
HANDLE* pSharedHandle,
DWORD Usage);
HRESULT STDMETHODCALLTYPE CreateDepthStencilSurfaceEx(
UINT Width,
UINT Height,
D3DFORMAT Format,
D3DMULTISAMPLE_TYPE MultiSample,
DWORD MultisampleQuality,
BOOL Discard,
IDirect3DSurface9** ppSurface,
HANDLE* pSharedHandle,
DWORD Usage);
HRESULT STDMETHODCALLTYPE ResetEx(
D3DPRESENT_PARAMETERS* pPresentationParameters,
D3DDISPLAYMODEEX* pFullscreenDisplayMode);
HRESULT STDMETHODCALLTYPE GetDisplayModeEx(
UINT iSwapChain,
D3DDISPLAYMODEEX* pMode,
D3DDISPLAYROTATION* pRotation);
HRESULT STDMETHODCALLTYPE CreateAdditionalSwapChainEx(
D3DPRESENT_PARAMETERS* pPresentationParameters,
const D3DDISPLAYMODEEX* pFullscreenDisplayMode,
IDirect3DSwapChain9** ppSwapChain);
HRESULT SetStateSamplerState(
DWORD StateSampler,
D3DSAMPLERSTATETYPE Type,
DWORD Value);
HRESULT SetStateTexture(DWORD StateSampler, IDirect3DBaseTexture9* pTexture);
HRESULT SetStateTransform(uint32_t idx, const D3DMATRIX* pMatrix);
VkPipelineStageFlags GetEnabledShaderStages() const {
return m_dxvkDevice->getShaderPipelineStages();
}
static DxvkDeviceFeatures GetDeviceFeatures(const Rc<DxvkAdapter>& adapter);
bool SupportsSWVP();
bool IsExtended();
HWND GetWindow();
Rc<DxvkDevice> GetDXVKDevice() {
return m_dxvkDevice;
}
D3D9_VK_FORMAT_MAPPING LookupFormat(
D3D9Format Format) const;
DxvkFormatInfo UnsupportedFormatInfo(
D3D9Format Format) const;
bool WaitForResource(
const Rc<DxvkResource>& Resource,
DWORD MapFlags);
/**
* \brief Locks a subresource of an image
*
* \param [in] Subresource The subresource of the image to lock
* \param [out] pLockedBox The returned locked box of the image, containing data ptr and strides
* \param [in] pBox The region of the subresource to lock. This offsets the returned data ptr
* \param [in] Flags The D3DLOCK_* flags to lock the image with
* \returns \c D3D_OK if the parameters are valid or D3DERR_INVALIDCALL if it fails.
*/
HRESULT LockImage(
D3D9CommonTexture* pResource,
UINT Face,
UINT Mip,
D3DLOCKED_BOX* pLockedBox,
const D3DBOX* pBox,
DWORD Flags);
uint32_t CalcImageLockOffset(
uint32_t SlicePitch,
uint32_t RowPitch,
const DxvkFormatInfo* FormatInfo,
const D3DBOX* pBox);
/**
* \brief Unlocks a subresource of an image
*
* Passthrough to device unlock.
* \param [in] Subresource The subresource of the image to unlock
* \returns \c D3D_OK if the parameters are valid or D3DERR_INVALIDCALL if it fails.
*/
HRESULT UnlockImage(
D3D9CommonTexture* pResource,
UINT Face,
UINT MipLevel);
HRESULT FlushImage(
D3D9CommonTexture* pResource,
UINT Subresource);
void GenerateMips(
D3D9CommonTexture* pResource);
HRESULT LockBuffer(
D3D9CommonBuffer* pResource,
UINT OffsetToLock,
UINT SizeToLock,
void** ppbData,
DWORD Flags);
HRESULT FlushBuffer(
D3D9CommonBuffer* pResource);
HRESULT UnlockBuffer(
D3D9CommonBuffer* pResource);
void SetupFPU();
int64_t DetermineInitialTextureMemory();
void CreateConstantBuffers();
void SynchronizeCsThread();
void Flush();
D3D9ShaderMasks GetShaderMasks();
void UpdateActiveRTs(uint32_t index);
void UpdateActiveRTTextures(uint32_t index);
void UpdateActiveHazards();
void MarkRenderHazards();
template <bool Points>
void UpdatePointMode();
void UpdateFog();
void BindFramebuffer();
void BindViewportAndScissor();
inline bool IsAlphaToCoverageEnabled() {
const bool alphaTest = m_state.renderStates[D3DRS_ALPHATESTENABLE] != 0;
return m_amdATOC || (m_nvATOC && alphaTest);
}
inline bool IsAlphaTestEnabled() {
return m_state.renderStates[D3DRS_ALPHATESTENABLE] && !IsAlphaToCoverageEnabled();
}
inline bool IsZTestEnabled() {
return m_state.renderStates[D3DRS_ZENABLE] && m_state.depthStencil != nullptr;
}
void BindMultiSampleState();
void BindBlendState();
void BindBlendFactor();
void BindDepthStencilState();
void BindDepthStencilRefrence();
void BindRasterizerState();
void BindAlphaTestState();
template <DxsoProgramType ShaderStage, typename HardwareLayoutType, typename SoftwareLayoutType, typename ShaderType>
inline void UploadHardwareConstantSet(void* pData, const SoftwareLayoutType& Src, const ShaderType& Shader);
template <typename SoftwareLayoutType, typename ShaderType>
inline void UploadSoftwareConstantSet(void* pData, const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout, const ShaderType& Shader);
template <DxsoProgramType ShaderStage, typename HardwareLayoutType, typename SoftwareLayoutType, typename ShaderType>
inline void UploadConstantSet(const SoftwareLayoutType& Src, const D3D9ConstantLayout& Layout, const ShaderType& Shader);
template <DxsoProgramType ShaderStage>
void UploadConstants();
void UpdateClipPlanes();
template <uint32_t Offset, uint32_t Length>
void UpdatePushConstant(const void* pData);
template <D3D9RenderStateItem Item>
void UpdatePushConstant();
void BindSampler(DWORD Sampler);
void BindTexture(DWORD SamplerSampler);
void UndirtySamplers();
void MarkSamplersDirty();
D3D9DrawInfo GenerateDrawInfo(
D3DPRIMITIVETYPE PrimitiveType,
UINT PrimitiveCount,
UINT InstanceCount);
uint32_t GetInstanceCount() const;
void PrepareDraw(D3DPRIMITIVETYPE PrimitiveType, bool up = false);
template <DxsoProgramType ShaderStage>
void BindShader(
const D3D9CommonShader* pShaderModule,
D3D9ShaderPermutation Permutation);
void BindInputLayout();
void BindVertexBuffer(
UINT Slot,
D3D9VertexBuffer* pBuffer,
UINT Offset,
UINT Stride);
void BindIndices();
D3D9DeviceLock LockDevice() {
return m_multithread.AcquireLock();
}
const D3D9Options* GetOptions() const {
return &m_d3d9Options;
}
Direct3DState9* GetRawState() {
return &m_state;
}
void Begin(D3D9Query* pQuery);
void End(D3D9Query* pQuery);
void SetVertexBoolBitfield(uint32_t idx, uint32_t mask, uint32_t bits);
void SetPixelBoolBitfield (uint32_t idx, uint32_t mask, uint32_t bits);
void FlushImplicit(BOOL StrongHint);
bool ChangeReportedMemory(int64_t delta) {
if (IsExtended())
return true;
int64_t availableMemory = m_availableMemory.fetch_add(delta);
return !m_d3d9Options.memoryTrackTest || availableMemory >= delta;
}
void ResolveZ();
void TransitionImage(D3D9CommonTexture* pResource, VkImageLayout NewLayout);
void TransformImage(
D3D9CommonTexture* pResource,
const VkImageSubresourceRange* pSubresources,
VkImageLayout OldLayout,
VkImageLayout NewLayout);
const D3D9ConstantLayout& GetVertexConstantLayout() { return m_vsLayout; }
const D3D9ConstantLayout& GetPixelConstantLayout() { return m_psLayout; }
HRESULT ResetState(D3DPRESENT_PARAMETERS* pPresentationParameters);
HRESULT ResetSwapChain(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode);
HRESULT InitialReset(D3DPRESENT_PARAMETERS* pPresentationParameters, D3DDISPLAYMODEEX* pFullscreenDisplayMode);
UINT GetSamplerCount() const {
return m_samplerCount.load();
}
private:
D3D9DeviceFlags m_flags;
uint32_t m_dirtySamplerStates = 0;
D3D9Adapter* m_adapter;
Rc<DxvkDevice> m_dxvkDevice;
Rc<DxvkDataBuffer> m_updateBuffer;
DxvkCsChunkPool m_csChunkPool;
dxvk::high_resolution_clock::time_point m_lastFlush
= dxvk::high_resolution_clock::now();
DxvkCsThread m_csThread;
bool m_csIsBusy = false;
uint32_t m_frameLatency = DefaultFrameLatency;
D3D9Initializer* m_initializer = nullptr;
D3D9FormatHelper* m_converter = nullptr;
DxvkCsChunkRef m_csChunk;
D3D9FFShaderModuleSet m_ffModules;
D3D9SWVPEmulator m_swvpEmulator;
DxvkCsChunkRef AllocCsChunk() {
DxvkCsChunk* chunk = m_csChunkPool.allocChunk(DxvkCsChunkFlag::SingleUse);
return DxvkCsChunkRef(chunk, &m_csChunkPool);
}
template<typename Cmd>
void EmitCs(Cmd&& command) {
if (unlikely(!m_csChunk->push(command))) {
EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
m_csChunk->push(command);
}
}
void EmitCsChunk(DxvkCsChunkRef&& chunk);
void FlushCsChunk() {
if (likely(!m_csChunk->empty())) {
EmitCsChunk(std::move(m_csChunk));
m_csChunk = AllocCsChunk();
}
}
bool CanSWVP() {
return m_behaviorFlags & (D3DCREATE_MIXED_VERTEXPROCESSING | D3DCREATE_SOFTWARE_VERTEXPROCESSING);
}
inline constexpr D3D9ShaderPermutation GetVertexShaderPermutation() {
return D3D9ShaderPermutations::None;
}
inline D3D9ShaderPermutation GetPixelShaderPermutation() {
if (unlikely(m_state.renderStates[D3DRS_SHADEMODE] == D3DSHADE_FLAT))
return D3D9ShaderPermutations::FlatShade;
return D3D9ShaderPermutations::None;
}
Com<D3D9InterfaceEx> m_parent;
D3DDEVTYPE m_deviceType;
HWND m_window;
DWORD m_behaviorFlags;
Direct3DState9 m_state;
Com<D3D9StateBlock> m_recorder;
D3D9Multithread m_multithread;
Rc<D3D9ShaderModuleSet> m_shaderModules;
D3D9ConstantSets m_consts[DxsoProgramTypes::Count];
Rc<DxvkBuffer> m_vsClipPlanes;
Rc<DxvkBuffer> m_vsFixedFunction;
Rc<DxvkBuffer> m_vsVertexBlend;
Rc<DxvkBuffer> m_psFixedFunction;
Rc<DxvkBuffer> m_psShared;
D3D9UPBufferSlice m_upBuffer;
const D3D9Options m_d3d9Options;
const DxsoOptions m_dxsoOptions;
BOOL m_isSWVP;
D3DPRESENT_PARAMETERS m_presentParams;
D3D9Cursor m_cursor;
Com<D3D9Surface, false> m_autoDepthStencil;
std::vector<
Com<D3D9SwapChainEx,
false>> m_swapchains;
std::unordered_map<
D3D9SamplerKey,
D3D9SamplerPair,
D3D9SamplerKeyHash,
D3D9SamplerKeyEq> m_samplers;
std::unordered_map<
DWORD,
Com<D3D9VertexDecl>> m_fvfTable;
D3D9InputAssemblyState m_iaState;
uint32_t m_instancedData = 0;
uint32_t m_lastSamplerTypeBitfield = 0;
uint32_t m_samplerTypeBitfield = 0;
uint32_t m_lastProjectionBitfield = 0;
uint32_t m_projectionBitfield = 0;
uint32_t m_lastPointMode = 0;
uint32_t m_activeRTs = 0;
uint32_t m_activeRTTextures = 0;
uint32_t m_activeHazards = 0;
uint32_t m_alphaSwizzleRTs = 0;
D3D9ViewportInfo m_viewportInfo;
std::atomic<int64_t> m_availableMemory = 0;
std::atomic<int32_t> m_samplerCount = 0;
bool m_amdATOC = false;
bool m_nvATOC = false;
bool m_ffZTest = false;
D3D9ConstantLayout m_vsLayout;
D3D9ConstantLayout m_psLayout;
void DetermineConstantLayouts(bool canSWVP);
D3D9UPBufferSlice AllocUpBuffer(VkDeviceSize size);
D3D9SwapChainEx* GetInternalSwapchain(UINT index);
bool ShouldRecord();
HRESULT CreateShaderModule(
D3D9CommonShader* pShaderModule,
VkShaderStageFlagBits ShaderStage,
const DWORD* pShaderBytecode,
const DxsoModuleInfo* pModuleInfo);
// So we don't do OOB.
template <DxsoProgramType ProgramType,
D3D9ConstantType ConstantType>
inline static constexpr uint32_t DetermineSoftwareRegCount() {
constexpr bool isVS = ProgramType == DxsoProgramType::VertexShader;
switch (ConstantType) {
default:
case D3D9ConstantType::Float: return isVS ? caps::MaxFloatConstantsSoftware : caps::MaxFloatConstantsPS;
case D3D9ConstantType::Int: return isVS ? caps::MaxOtherConstantsSoftware : caps::MaxOtherConstants;
case D3D9ConstantType::Bool: return isVS ? caps::MaxOtherConstantsSoftware : caps::MaxOtherConstants;
}
}
// So we don't copy more than we need.
template <DxsoProgramType ProgramType,
D3D9ConstantType ConstantType>
inline uint32_t DetermineHardwareRegCount() const {
const auto& layout = ProgramType == DxsoProgramType::VertexShader
? m_vsLayout : m_psLayout;
switch (ConstantType) {
default:
case D3D9ConstantType::Float: return layout.floatCount;
case D3D9ConstantType::Int: return layout.intCount;
case D3D9ConstantType::Bool: return layout.boolCount;
}
}
inline uint32_t GetFrameLatency() {
return m_frameLatency;
}
template <
DxsoProgramType ProgramType,
D3D9ConstantType ConstantType,
typename T>
HRESULT SetShaderConstants(
UINT StartRegister,
const T* pConstantData,
UINT Count);
template <
DxsoProgramType ProgramType,
D3D9ConstantType ConstantType,
typename T>
HRESULT GetShaderConstants(
UINT StartRegister,
T* pConstantData,
UINT Count) {
auto GetHelper = [&] (const auto& set) {
const uint32_t regCountHardware = DetermineHardwareRegCount<ProgramType, ConstantType>();
constexpr uint32_t regCountSoftware = DetermineSoftwareRegCount<ProgramType, ConstantType>();
if (StartRegister + Count > regCountSoftware)
return D3DERR_INVALIDCALL;
Count = UINT(
std::max<INT>(
std::clamp<INT>(Count + StartRegister, 0, regCountHardware) - INT(StartRegister),
0));
if (Count == 0)
return D3D_OK;
if (pConstantData == nullptr)
return D3DERR_INVALIDCALL;
if constexpr (ConstantType == D3D9ConstantType::Float) {
auto begin = &set.fConsts[StartRegister];
auto end = &begin[Count];
std::copy(begin, end, reinterpret_cast<Vector4*>(pConstantData));
}
else if constexpr (ConstantType == D3D9ConstantType::Int) {
auto begin = &set.iConsts[StartRegister];
auto end = &begin[Count];
std::copy(begin, end, reinterpret_cast<Vector4i*>(pConstantData));
}
else {
for (uint32_t i = 0; i < Count; i++) {
const uint32_t constantIdx = StartRegister + i;
const uint32_t arrayIdx = constantIdx / 32;
const uint32_t bitIdx = constantIdx % 32;
const uint32_t bit = (1u << bitIdx);
bool constValue = set.bConsts[arrayIdx] & bit;
pConstantData[i] = constValue ? TRUE : FALSE;
}
}
return D3D_OK;
};
return ProgramType == DxsoProgramTypes::VertexShader
? GetHelper(m_state.vsConsts)
: GetHelper(m_state.psConsts);
}
void UpdateFixedFunctionVS();
void UpdateFixedFunctionPS();
void ApplyPrimitiveType(
DxvkContext* pContext,
D3DPRIMITIVETYPE PrimType);
bool UseProgrammableVS();
bool UseProgrammablePS();
void UpdateSamplerSpecConsant(uint32_t value);
void UpdateProjectionSpecConstant(uint32_t value);
};
}