1
0
mirror of https://github.com/narzoul/DDrawCompat synced 2024-12-30 08:55:36 +01:00

Moved z-buffer bit depth caps fix to driver level

This commit is contained in:
narzoul 2021-01-07 01:06:37 +01:00
parent f3718272cd
commit 050248a552
7 changed files with 94 additions and 240 deletions

View File

@ -1,12 +1,32 @@
#include <guiddef.h>
#include <d3dnthal.h>
#include <map>
#include "D3dDdi/Adapter.h"
#include "D3dDdi/AdapterFuncs.h"
#include "D3dDdi/DeviceCallbacks.h"
#include "D3dDdi/DeviceFuncs.h"
#include <D3dDdi/Adapter.h>
#include <D3dDdi/AdapterFuncs.h>
#include <D3dDdi/DeviceCallbacks.h>
#include <D3dDdi/DeviceFuncs.h>
namespace
{
DWORD getSupportedZBufferBitDepths(HANDLE adapter);
std::string bitDepthsToString(DWORD bitDepths)
{
std::string result;
if (bitDepths & DDBD_8) { result += ", 8"; }
if (bitDepths & DDBD_16) { result += ", 16"; }
if (bitDepths & DDBD_24) { result += ", 24"; }
if (bitDepths & DDBD_32) { result += ", 32"; }
if (result.empty())
{
return "\"\"";
}
return '"' + result.substr(2) + '"';
}
HRESULT APIENTRY closeAdapter(HANDLE hAdapter)
{
HRESULT result = D3dDdi::AdapterFuncs::s_origVtablePtr->pfnCloseAdapter(hAdapter);
@ -33,13 +53,78 @@ namespace
HRESULT APIENTRY getCaps(HANDLE hAdapter, const D3DDDIARG_GETCAPS* pData)
{
HRESULT result = D3dDdi::AdapterFuncs::s_origVtablePtr->pfnGetCaps(hAdapter, pData);
if (SUCCEEDED(result) && D3DDDICAPS_DDRAW == pData->Type)
if (FAILED(result))
{
return result;
}
switch (pData->Type)
{
case D3DDDICAPS_DDRAW:
static_cast<DDRAW_CAPS*>(pData->pData)->FxCaps =
DDRAW_FXCAPS_BLTMIRRORLEFTRIGHT | DDRAW_FXCAPS_BLTMIRRORUPDOWN;
break;
case D3DDDICAPS_GETD3D3CAPS:
{
auto& caps = static_cast<D3DNTHAL_GLOBALDRIVERDATA*>(pData->pData)->hwCaps;
if (caps.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH)
{
const DWORD supportedZBufferBitDepths = getSupportedZBufferBitDepths(hAdapter);
if (supportedZBufferBitDepths != caps.dwDeviceZBufferBitDepth)
{
LOG_ONCE("Incorrect z-buffer bit depth capabilities detected; changed from "
<< bitDepthsToString(caps.dwDeviceZBufferBitDepth) << " to "
<< bitDepthsToString(supportedZBufferBitDepths));
caps.dwDeviceZBufferBitDepth = supportedZBufferBitDepths;
}
}
break;
}
}
return result;
}
DWORD getSupportedZBufferBitDepths(HANDLE adapter)
{
UINT formatCount = 0;
D3DDDIARG_GETCAPS caps = {};
caps.Type = D3DDDICAPS_GETFORMATCOUNT;
caps.pData = &formatCount;
caps.DataSize = sizeof(formatCount);
D3dDdi::AdapterFuncs::s_origVtablePtr->pfnGetCaps(adapter, &caps);
std::vector<FORMATOP> formatOp(formatCount);
caps.Type = D3DDDICAPS_GETFORMATDATA;
caps.pData = formatOp.data();
caps.DataSize = formatCount * sizeof(FORMATOP);
D3dDdi::AdapterFuncs::s_origVtablePtr->pfnGetCaps(adapter, &caps);
DWORD supportedZBufferBitDepths = 0;
for (UINT i = 0; i < formatCount; ++i)
{
if (formatOp[i].Operations & (FORMATOP_ZSTENCIL | FORMATOP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH))
{
switch (formatOp[i].Format)
{
case D3DDDIFMT_D16:
supportedZBufferBitDepths |= DDBD_16;
break;
case D3DDDIFMT_X8D24:
supportedZBufferBitDepths |= DDBD_24;
break;
case D3DDDIFMT_D32:
supportedZBufferBitDepths |= DDBD_32;
break;
}
}
}
return supportedZBufferBitDepths;
}
}
namespace D3dDdi

View File

@ -193,7 +193,6 @@
<ClInclude Include="DDraw\Visitors\DirectDrawPaletteVtblVisitor.h" />
<ClInclude Include="DDraw\Visitors\DirectDrawSurfaceVtblVisitor.h" />
<ClInclude Include="DDraw\Visitors\DirectDrawVtblVisitor.h" />
<ClInclude Include="Direct3d\DepthBuffer.h" />
<ClInclude Include="Direct3d\Direct3d.h" />
<ClInclude Include="Direct3d\Direct3dDevice.h" />
<ClInclude Include="Direct3d\Direct3dExecuteBuffer.h" />
@ -275,7 +274,6 @@
<ClCompile Include="DDraw\Surfaces\PrimarySurfaceImpl.cpp" />
<ClCompile Include="DDraw\Surfaces\Surface.cpp" />
<ClCompile Include="DDraw\Surfaces\SurfaceImpl.cpp" />
<ClCompile Include="Direct3d\DepthBuffer.cpp" />
<ClCompile Include="Direct3d\Direct3d.cpp" />
<ClCompile Include="Direct3d\Direct3dDevice.cpp" />
<ClCompile Include="Direct3d\Direct3dExecuteBuffer.cpp" />

View File

@ -138,9 +138,6 @@
<ClInclude Include="Direct3d\Direct3dDevice.h">
<Filter>Header Files\Direct3d</Filter>
</ClInclude>
<ClInclude Include="Direct3d\DepthBuffer.h">
<Filter>Header Files\Direct3d</Filter>
</ClInclude>
<ClInclude Include="Direct3d\Types.h">
<Filter>Header Files\Direct3d</Filter>
</ClInclude>
@ -455,9 +452,6 @@
<ClCompile Include="Direct3d\Direct3dDevice.cpp">
<Filter>Source Files\Direct3d</Filter>
</ClCompile>
<ClCompile Include="Direct3d\DepthBuffer.cpp">
<Filter>Source Files\Direct3d</Filter>
</ClCompile>
<ClCompile Include="Direct3d\Hooks.cpp">
<Filter>Source Files\Direct3d</Filter>
</ClCompile>

View File

@ -1,124 +0,0 @@
#include <algorithm>
#include <vector>
#include "Direct3d/DepthBuffer.h"
namespace
{
std::string bitDepthsToString(DWORD bitDepths)
{
std::string result;
if (bitDepths & DDBD_8) { result += ", 8"; }
if (bitDepths & DDBD_16) { result += ", 16"; }
if (bitDepths & DDBD_24) { result += ", 24"; }
if (bitDepths & DDBD_32) { result += ", 32"; }
result = '"' + result.substr(2) + '"';
return result;
}
HRESULT CALLBACK enumZBufferFormatsCallback(LPDDPIXELFORMAT lpDDPixFmt, LPVOID lpContext)
{
LOG_FUNC("CompatDepthBuffer::enumZBufferFormatsCallback", lpDDPixFmt, lpContext);
if (DDPF_ZBUFFER == lpDDPixFmt->dwFlags &&
(static_cast<uint64_t>(1) << lpDDPixFmt->dwZBufferBitDepth) - 1 == lpDDPixFmt->dwZBitMask)
{
DWORD& supportedBitDepths = *reinterpret_cast<DWORD*>(lpContext);
switch (lpDDPixFmt->dwZBufferBitDepth)
{
case 8: supportedBitDepths |= DDBD_8; break;
case 16: supportedBitDepths |= DDBD_16; break;
case 24: supportedBitDepths |= DDBD_24; break;
case 32: supportedBitDepths |= DDBD_32; break;
}
}
return LOG_RESULT(D3DENUMRET_OK);
}
GUID getDeviceGuid(const D3DDEVICEDESC& /*desc*/)
{
return IID_IDirect3DHALDevice;
}
GUID getDeviceGuid(const D3DDEVICEDESC7& desc)
{
return desc.deviceGUID;
}
template <typename TDirect3d>
DWORD getSupportedZBufferBitDepths(CompatPtr<TDirect3d> d3d, const GUID& deviceGuid)
{
DWORD supportedBitDepths = 0;
if (d3d)
{
d3d->EnumZBufferFormats(d3d, deviceGuid, &enumZBufferFormatsCallback, &supportedBitDepths);
}
return supportedBitDepths;
}
bool isHardwareZBufferSupported(const D3DDEVICEDESC& desc)
{
return (desc.dwFlags & D3DDD_DEVICEZBUFFERBITDEPTH) && 0 != desc.dwDeviceZBufferBitDepth;
}
bool isHardwareZBufferSupported(const D3DDEVICEDESC7& desc)
{
return 0 != desc.dwDeviceZBufferBitDepth &&
(IID_IDirect3DHALDevice == desc.deviceGUID || IID_IDirect3DTnLHalDevice == desc.deviceGUID);
}
void logSupportedZBufferBitDepthsChanged(
CompatPtr<IDirectDraw7> dd, const GUID& d3dGuid, DWORD oldBitDepths, DWORD newBitDepths)
{
struct DeviceId
{
GUID directDrawGuid;
GUID direct3dGuid;
bool operator==(const DeviceId& rhs) const
{
return directDrawGuid == rhs.directDrawGuid && direct3dGuid == rhs.direct3dGuid;
}
};
DDDEVICEIDENTIFIER2 deviceIdentifier = {};
dd->GetDeviceIdentifier(dd, &deviceIdentifier, 0);
const DeviceId deviceId = { deviceIdentifier.guidDeviceIdentifier, d3dGuid };
static std::vector<DeviceId> loggedDevices;
if (loggedDevices.end() != std::find(loggedDevices.begin(), loggedDevices.end(), deviceId))
{
return;
}
loggedDevices.push_back(deviceId);
Compat::Log() << "Incorrect z-buffer bit depth capabilities detected for \"" <<
deviceIdentifier.szDescription << "\" / " <<
(IID_IDirect3DTnLHalDevice == d3dGuid ? "Direct3D T&L HAL" : "Direct3D HAL") <<
"; changed from " << bitDepthsToString(oldBitDepths) << " to " << bitDepthsToString(newBitDepths);
}
}
namespace Direct3d
{
namespace DepthBuffer
{
template <typename TDirect3d, typename TD3dDeviceDesc>
void fixSupportedZBufferBitDepths(
CompatPtr<TDirect3d> d3d, TD3dDeviceDesc& desc)
{
if (isHardwareZBufferSupported(desc))
{
const DWORD supportedBitDepths = getSupportedZBufferBitDepths(d3d, getDeviceGuid(desc));
if (0 != supportedBitDepths && supportedBitDepths != desc.dwDeviceZBufferBitDepth)
{
logSupportedZBufferBitDepthsChanged(
d3d, getDeviceGuid(desc), desc.dwDeviceZBufferBitDepth, supportedBitDepths);
desc.dwDeviceZBufferBitDepth = supportedBitDepths;
}
}
}
template void fixSupportedZBufferBitDepths(CompatPtr<IDirect3D3>, D3DDEVICEDESC&);
template void fixSupportedZBufferBitDepths(CompatPtr<IDirect3D7>, D3DDEVICEDESC7&);
}
}

View File

@ -1,14 +0,0 @@
#pragma once
#include <guiddef.h>
#include "Common/CompatPtr.h"
namespace Direct3d
{
namespace DepthBuffer
{
template <typename TDirect3d, typename TD3dDeviceDesc>
void fixSupportedZBufferBitDepths(CompatPtr<TDirect3d> d3d, TD3dDeviceDesc& desc);
}
}

View File

@ -1,19 +1,10 @@
#include "Common/CompatPtr.h"
#include "Direct3d/DepthBuffer.h"
#include "Direct3d/Direct3d.h"
#include "Direct3d/Direct3dDevice.h"
#include "Direct3d/Types.h"
#include <Common/CompatPtr.h>
#include <Direct3d/Direct3d.h>
#include <Direct3d/Direct3dDevice.h>
#include <Direct3d/Types.h>
namespace
{
template <typename TDirect3d>
struct EnumDevicesParams
{
CompatPtr<TDirect3d> d3d;
typename Direct3d::Types<TDirect3d>::TD3dEnumDevicesCallback enumDevicesCallback;
void* userArg;
};
template <typename TDirect3d, typename TDirectDrawSurface, typename TDirect3dDevice, typename... Params>
HRESULT STDMETHODCALLTYPE createDevice(
TDirect3d* This,
@ -31,50 +22,6 @@ namespace
return result;
}
HRESULT CALLBACK d3dEnumDevicesCallback(
GUID* lpGuid,
LPSTR lpDeviceDescription,
LPSTR lpDeviceName,
LPD3DDEVICEDESC lpD3DHWDeviceDesc,
LPD3DDEVICEDESC lpD3DHELDeviceDesc,
LPVOID lpContext)
{
auto& params = *reinterpret_cast<EnumDevicesParams<IDirect3D3>*>(lpContext);
Direct3d::DepthBuffer::fixSupportedZBufferBitDepths<IDirect3D3>(params.d3d, *lpD3DHWDeviceDesc);
return params.enumDevicesCallback(lpGuid, lpDeviceDescription, lpDeviceName,
lpD3DHWDeviceDesc, lpD3DHELDeviceDesc, params.userArg);
}
HRESULT CALLBACK d3dEnumDevicesCallback(
LPSTR lpDeviceDescription,
LPSTR lpDeviceName,
LPD3DDEVICEDESC7 lpD3DDeviceDesc,
LPVOID lpContext)
{
auto& params = *reinterpret_cast<EnumDevicesParams<IDirect3D7>*>(lpContext);
Direct3d::DepthBuffer::fixSupportedZBufferBitDepths<IDirect3D7>(params.d3d, *lpD3DDeviceDesc);
return params.enumDevicesCallback(lpDeviceDescription, lpDeviceName,
lpD3DDeviceDesc, params.userArg);
}
template <typename TDirect3d, typename TD3dEnumDevicesCallback>
HRESULT STDMETHODCALLTYPE enumDevices(
TDirect3d* This, TD3dEnumDevicesCallback lpEnumDevicesCallback, LPVOID lpUserArg)
{
if (!lpEnumDevicesCallback)
{
return CompatVtable<Vtable<TDirect3d>>::s_origVtable.EnumDevices(
This, lpEnumDevicesCallback, lpUserArg);
}
typedef typename Direct3d::Types<TDirect3d>::TDirect3dHighest TDirect3dHighest;
CompatPtr<TDirect3dHighest> d3d(Compat::queryInterface<TDirect3dHighest>(This));
EnumDevicesParams<TDirect3dHighest> params = { d3d, lpEnumDevicesCallback, lpUserArg };
return CompatVtable<Vtable<TDirect3d>>::s_origVtable.EnumDevices(
This, &d3dEnumDevicesCallback, &params);
}
void setCompatVtable2(IDirect3DVtbl& /*vtable*/)
{
}
@ -91,8 +38,6 @@ namespace Direct3d
template <typename TDirect3d>
void Direct3d<TDirect3d>::setCompatVtable(Vtable<TDirect3d>& vtable)
{
vtable.EnumDevices = &enumDevices;
// No need to fix FindDevice since it uses EnumDevices
setCompatVtable2(vtable);
}

View File

@ -1,7 +1,6 @@
#include <Common/CompatPtr.h>
#include <Common/CompatRef.h>
#include <D3dDdi/Device.h>
#include <Direct3d/DepthBuffer.h>
#include <Direct3d/Direct3dDevice.h>
#include <Direct3d/Types.h>
@ -18,34 +17,6 @@ namespace
return result;
}
template <typename TDirect3dDevice, typename TD3dDeviceDesc>
void fixSupportedZBufferBitDepths(CompatRef<TDirect3dDevice> d3dDevice, TD3dDeviceDesc& desc)
{
typedef typename Direct3d::Types<TDirect3dDevice>::TDirect3d TDirect3d;
CompatPtr<TDirect3d> d3d;
if (SUCCEEDED(CompatVtable<Vtable<TDirect3dDevice>>::s_origVtable.GetDirect3D(
&d3dDevice, &d3d.getRef())))
{
typedef typename Direct3d::Types<TDirect3dDevice>::TDirect3dHighest TDirect3dHighest;
Direct3d::DepthBuffer::fixSupportedZBufferBitDepths<TDirect3dHighest>(d3d, desc);
}
}
template <typename TDirect3dDevice, typename TD3dDeviceDesc, typename... Params>
HRESULT STDMETHODCALLTYPE getCaps(
TDirect3dDevice* This,
TD3dDeviceDesc* lpD3DHWDevDesc,
Params... params)
{
HRESULT result = CompatVtable<Vtable<TDirect3dDevice>>::s_origVtable.GetCaps(
This, lpD3DHWDevDesc, params...);
if (SUCCEEDED(result))
{
fixSupportedZBufferBitDepths<TDirect3dDevice>(*This, *lpD3DHWDevDesc);
}
return result;
}
void setCompatVtable(IDirect3DDeviceVtbl& vtable)
{
vtable.Execute = &execute;
@ -63,7 +34,6 @@ namespace Direct3d
void Direct3dDevice<TDirect3dDevice>::setCompatVtable(Vtable<TDirect3dDevice>& vtable)
{
::setCompatVtable(vtable);
vtable.GetCaps = &getCaps;
}
template Direct3dDevice<IDirect3DDevice>;