2019-12-16 04:28:01 +01:00
|
|
|
#include "d3d9_adapter.h"
|
|
|
|
|
|
|
|
#include "d3d9_interface.h"
|
|
|
|
#include "d3d9_monitor.h"
|
|
|
|
#include "d3d9_caps.h"
|
|
|
|
#include "d3d9_util.h"
|
|
|
|
|
|
|
|
#include "../util/util_bit.h"
|
|
|
|
#include "../util/util_luid.h"
|
|
|
|
#include "../util/util_ratio.h"
|
|
|
|
|
|
|
|
#include <cfloat>
|
|
|
|
|
|
|
|
namespace dxvk {
|
|
|
|
|
|
|
|
const char* GetDriverDLL(DxvkGpuVendor vendor) {
|
|
|
|
switch (vendor) {
|
|
|
|
default:
|
|
|
|
case DxvkGpuVendor::Nvidia: return "nvd3dum.dll";
|
|
|
|
|
|
|
|
#if defined(__x86_64__) || defined(_M_X64)
|
|
|
|
case DxvkGpuVendor::Amd: return "aticfx64.dll";
|
|
|
|
case DxvkGpuVendor::Intel: return "igdumd64.dll";
|
|
|
|
#else
|
|
|
|
case DxvkGpuVendor::Amd: return "aticfx32.dll";
|
|
|
|
case DxvkGpuVendor::Intel: return "igdumd32.dll";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
D3D9Adapter::D3D9Adapter(
|
|
|
|
D3D9InterfaceEx* pParent,
|
|
|
|
Rc<DxvkAdapter> Adapter,
|
|
|
|
UINT Ordinal)
|
|
|
|
: m_parent (pParent)
|
|
|
|
, m_adapter (Adapter)
|
|
|
|
, m_ordinal (Ordinal)
|
|
|
|
, m_modeCacheFormat (D3D9Format::Unknown)
|
|
|
|
, m_d3d9Formats (Adapter, m_parent->GetOptions()) {
|
|
|
|
m_adapter->logAdapterInfo();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::GetAdapterIdentifier(
|
|
|
|
DWORD Flags,
|
|
|
|
D3DADAPTER_IDENTIFIER9* pIdentifier) {
|
|
|
|
if (unlikely(pIdentifier == nullptr))
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
auto& options = m_parent->GetOptions();
|
|
|
|
|
|
|
|
const auto& props = m_adapter->deviceProperties();
|
|
|
|
|
|
|
|
::MONITORINFOEXA monInfo;
|
|
|
|
monInfo.cbSize = sizeof(monInfo);
|
|
|
|
|
|
|
|
if (!::GetMonitorInfoA(GetDefaultMonitor(), reinterpret_cast<MONITORINFO*>(&monInfo))) {
|
|
|
|
Logger::err("D3D9Adapter::GetAdapterIdentifier: Failed to query monitor info");
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
GUID guid = bit::cast<GUID>(m_adapter->devicePropertiesExt().coreDeviceId.deviceUUID);
|
|
|
|
|
|
|
|
uint32_t vendorId = options.customVendorId == -1 ? props.vendorID : uint32_t(options.customVendorId);
|
|
|
|
uint32_t deviceId = options.customDeviceId == -1 ? props.deviceID : uint32_t(options.customDeviceId);
|
|
|
|
const char* desc = options.customDeviceDesc.empty() ? props.deviceName : options.customDeviceDesc.c_str();
|
|
|
|
const char* driver = GetDriverDLL(DxvkGpuVendor(vendorId));
|
|
|
|
|
|
|
|
std::strncpy(pIdentifier->Description, desc, countof(pIdentifier->Description));
|
|
|
|
std::strncpy(pIdentifier->DeviceName, monInfo.szDevice, countof(pIdentifier->DeviceName)); // The GDI device name. Not the actual device name.
|
|
|
|
std::strncpy(pIdentifier->Driver, driver, countof(pIdentifier->Driver)); // This is the driver's dll.
|
|
|
|
|
|
|
|
pIdentifier->DeviceIdentifier = guid;
|
|
|
|
pIdentifier->DeviceId = deviceId;
|
|
|
|
pIdentifier->VendorId = vendorId;
|
|
|
|
pIdentifier->Revision = 0;
|
|
|
|
pIdentifier->SubSysId = 0;
|
|
|
|
pIdentifier->WHQLLevel = m_parent->IsExtended() ? 1 : 0; // This doesn't check with the driver on Direct3D9Ex and is always 1.
|
|
|
|
pIdentifier->DriverVersion.QuadPart = INT64_MAX;
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::CheckDeviceType(
|
|
|
|
D3DDEVTYPE DevType,
|
|
|
|
D3D9Format AdapterFormat,
|
|
|
|
D3D9Format BackBufferFormat,
|
|
|
|
BOOL bWindowed) {
|
|
|
|
if (!IsSupportedBackBufferFormat(
|
|
|
|
AdapterFormat, BackBufferFormat, bWindowed))
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::CheckDeviceFormat(
|
|
|
|
D3DDEVTYPE DeviceType,
|
|
|
|
D3D9Format AdapterFormat,
|
|
|
|
DWORD Usage,
|
|
|
|
D3DRESOURCETYPE RType,
|
|
|
|
D3D9Format CheckFormat) {
|
2020-02-14 01:46:02 +01:00
|
|
|
if (!IsSupportedAdapterFormat(AdapterFormat, false))
|
2019-12-16 04:28:01 +01:00
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
const bool dmap = Usage & D3DUSAGE_DMAP;
|
|
|
|
const bool rt = Usage & D3DUSAGE_RENDERTARGET;
|
|
|
|
const bool ds = Usage & D3DUSAGE_DEPTHSTENCIL;
|
|
|
|
|
|
|
|
const bool surface = RType == D3DRTYPE_SURFACE;
|
|
|
|
const bool texture = RType == D3DRTYPE_TEXTURE;
|
|
|
|
|
|
|
|
const bool twoDimensional = surface || texture;
|
|
|
|
|
|
|
|
const bool srgb = (Usage & (D3DUSAGE_QUERY_SRGBREAD | D3DUSAGE_QUERY_SRGBWRITE)) != 0;
|
|
|
|
|
|
|
|
if (CheckFormat == D3D9Format::INST)
|
|
|
|
return D3D_OK;
|
|
|
|
|
|
|
|
if (rt && CheckFormat == D3D9Format::A8 && m_parent->GetOptions().disableA8RT)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (ds && !IsDepthFormat(CheckFormat))
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (rt && CheckFormat == D3D9Format::NULL_FORMAT && twoDimensional)
|
|
|
|
return D3D_OK;
|
|
|
|
|
|
|
|
if (rt && CheckFormat == D3D9Format::RESZ && surface)
|
|
|
|
return D3D_OK;
|
|
|
|
|
|
|
|
if (CheckFormat == D3D9Format::ATOC && surface)
|
|
|
|
return D3D_OK;
|
|
|
|
|
2020-01-28 02:50:53 +01:00
|
|
|
if (m_adapter->features().core.features.depthBounds) {
|
|
|
|
if (CheckFormat == D3D9Format::NVDB && surface)
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
2019-12-16 04:28:01 +01:00
|
|
|
|
|
|
|
// I really don't want to support this...
|
|
|
|
if (dmap)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
auto mapping = m_d3d9Formats.GetFormatMapping(CheckFormat);
|
|
|
|
if (mapping.FormatColor == VK_FORMAT_UNDEFINED)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (mapping.FormatSrgb == VK_FORMAT_UNDEFINED && srgb)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (RType == D3DRTYPE_VERTEXBUFFER || RType == D3DRTYPE_INDEXBUFFER)
|
|
|
|
return D3D_OK;
|
|
|
|
|
|
|
|
// Let's actually ask Vulkan now that we got some quirks out the way!
|
|
|
|
|
|
|
|
return CheckDeviceVkFormat(mapping.FormatColor, Usage, RType);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::CheckDeviceMultiSampleType(
|
|
|
|
D3DDEVTYPE DeviceType,
|
|
|
|
D3D9Format SurfaceFormat,
|
|
|
|
BOOL Windowed,
|
|
|
|
D3DMULTISAMPLE_TYPE MultiSampleType,
|
|
|
|
DWORD* pQualityLevels) {
|
|
|
|
if (pQualityLevels != nullptr)
|
|
|
|
*pQualityLevels = 1;
|
|
|
|
|
|
|
|
auto dst = ConvertFormatUnfixed(SurfaceFormat);
|
|
|
|
if (dst.FormatColor == VK_FORMAT_UNDEFINED)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (MultiSampleType != D3DMULTISAMPLE_NONE
|
|
|
|
&& (SurfaceFormat == D3D9Format::D32_LOCKABLE
|
|
|
|
|| SurfaceFormat == D3D9Format::D32F_LOCKABLE
|
|
|
|
|| SurfaceFormat == D3D9Format::D16_LOCKABLE))
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
uint32_t sampleCount = std::max<uint32_t>(MultiSampleType, 1u);
|
|
|
|
|
|
|
|
// Check if this is a power of two...
|
|
|
|
if (sampleCount & (sampleCount - 1))
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
// Therefore...
|
|
|
|
VkSampleCountFlags sampleFlags = VkSampleCountFlags(sampleCount);
|
|
|
|
|
|
|
|
auto availableFlags = !IsDepthFormat(SurfaceFormat)
|
|
|
|
? m_adapter->deviceProperties().limits.framebufferColorSampleCounts
|
|
|
|
: m_adapter->deviceProperties().limits.framebufferDepthSampleCounts;
|
|
|
|
|
|
|
|
if (!(availableFlags & sampleFlags))
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (pQualityLevels != nullptr) {
|
|
|
|
if (MultiSampleType == D3DMULTISAMPLE_NONMASKABLE)
|
|
|
|
*pQualityLevels = (32 - bit::lzcnt(availableFlags));
|
|
|
|
else
|
|
|
|
*pQualityLevels = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::CheckDepthStencilMatch(
|
|
|
|
D3DDEVTYPE DeviceType,
|
|
|
|
D3D9Format AdapterFormat,
|
|
|
|
D3D9Format RenderTargetFormat,
|
|
|
|
D3D9Format DepthStencilFormat) {
|
2020-02-14 01:46:02 +01:00
|
|
|
if (!IsSupportedAdapterFormat(AdapterFormat, false))
|
2019-12-16 04:28:01 +01:00
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
if (!IsDepthFormat(DepthStencilFormat))
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
auto mapping = ConvertFormatUnfixed(RenderTargetFormat);
|
|
|
|
if (mapping.FormatColor == VK_FORMAT_UNDEFINED)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::CheckDeviceFormatConversion(
|
|
|
|
D3DDEVTYPE DeviceType,
|
|
|
|
D3D9Format SourceFormat,
|
|
|
|
D3D9Format TargetFormat) {
|
|
|
|
bool sourceSupported = IsSupportedBackBufferFormat(SourceFormat, FALSE);
|
|
|
|
bool targetSupported = TargetFormat == D3D9Format::X1R5G5B5
|
|
|
|
|| TargetFormat == D3D9Format::A1R5G5B5
|
|
|
|
|| TargetFormat == D3D9Format::R5G6B5
|
|
|
|
// || TargetFormat == D3D9Format::R8G8B8 <-- We don't support R8G8B8
|
|
|
|
|| TargetFormat == D3D9Format::X8R8G8B8
|
|
|
|
|| TargetFormat == D3D9Format::A8R8G8B8
|
|
|
|
|| TargetFormat == D3D9Format::A2R10G10B10
|
|
|
|
|| TargetFormat == D3D9Format::A16B16G16R16
|
|
|
|
|| TargetFormat == D3D9Format::A2B10G10R10
|
|
|
|
|| TargetFormat == D3D9Format::A8B8G8R8
|
|
|
|
|| TargetFormat == D3D9Format::X8B8G8R8
|
|
|
|
|| TargetFormat == D3D9Format::A16B16G16R16F
|
|
|
|
|| TargetFormat == D3D9Format::A32B32G32R32F;
|
|
|
|
|
|
|
|
return (sourceSupported && targetSupported)
|
|
|
|
? D3D_OK
|
|
|
|
: D3DERR_NOTAVAILABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::GetDeviceCaps(
|
|
|
|
D3DDEVTYPE DeviceType,
|
|
|
|
D3DCAPS9* pCaps) {
|
|
|
|
using namespace dxvk::caps;
|
|
|
|
|
|
|
|
if (pCaps == nullptr)
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
auto& options = m_parent->GetOptions();
|
|
|
|
|
|
|
|
// TODO: Actually care about what the adapter supports here.
|
|
|
|
// ^ For Intel and older cards most likely here.
|
|
|
|
|
|
|
|
// Device Type
|
|
|
|
pCaps->DeviceType = DeviceType;
|
|
|
|
// Adapter Id
|
|
|
|
pCaps->AdapterOrdinal = m_ordinal;
|
|
|
|
// Caps 1
|
|
|
|
pCaps->Caps = D3DCAPS_READ_SCANLINE;
|
|
|
|
// Caps 2
|
|
|
|
pCaps->Caps2 = D3DCAPS2_FULLSCREENGAMMA
|
|
|
|
/* | D3DCAPS2_CANCALIBRATEGAMMA */
|
|
|
|
/* | D3DCAPS2_RESERVED */
|
|
|
|
/* | D3DCAPS2_CANMANAGERESOURCE */
|
|
|
|
| D3DCAPS2_DYNAMICTEXTURES
|
|
|
|
| D3DCAPS2_CANAUTOGENMIPMAP
|
|
|
|
/* | D3DCAPS2_CANSHARERESOURCE */;
|
|
|
|
// Caps 3
|
|
|
|
pCaps->Caps3 = D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD
|
|
|
|
| D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION
|
|
|
|
| D3DCAPS3_COPY_TO_VIDMEM
|
|
|
|
| D3DCAPS3_COPY_TO_SYSTEMMEM
|
|
|
|
/* | D3DCAPS3_DXVAHD */
|
|
|
|
/* | D3DCAPS3_DXVAHD_LIMITED */;
|
|
|
|
// Presentation Intervals
|
|
|
|
pCaps->PresentationIntervals = D3DPRESENT_INTERVAL_DEFAULT
|
|
|
|
| D3DPRESENT_INTERVAL_ONE
|
|
|
|
| D3DPRESENT_INTERVAL_TWO
|
|
|
|
| D3DPRESENT_INTERVAL_THREE
|
|
|
|
| D3DPRESENT_INTERVAL_FOUR
|
|
|
|
| D3DPRESENT_INTERVAL_IMMEDIATE;
|
|
|
|
// Cursor
|
|
|
|
pCaps->CursorCaps = D3DCURSORCAPS_COLOR; // I do not support Cursor yet, but I don't want to say I don't support it for compatibility reasons.
|
|
|
|
// Dev Caps
|
|
|
|
pCaps->DevCaps = D3DDEVCAPS_EXECUTESYSTEMMEMORY
|
|
|
|
| D3DDEVCAPS_EXECUTEVIDEOMEMORY
|
|
|
|
| D3DDEVCAPS_TLVERTEXSYSTEMMEMORY
|
|
|
|
| D3DDEVCAPS_TLVERTEXVIDEOMEMORY
|
|
|
|
/* | D3DDEVCAPS_TEXTURESYSTEMMEMORY */
|
|
|
|
| D3DDEVCAPS_TEXTUREVIDEOMEMORY
|
|
|
|
| D3DDEVCAPS_DRAWPRIMTLVERTEX
|
|
|
|
| D3DDEVCAPS_CANRENDERAFTERFLIP
|
|
|
|
| D3DDEVCAPS_TEXTURENONLOCALVIDMEM
|
|
|
|
| D3DDEVCAPS_DRAWPRIMITIVES2
|
|
|
|
/* | D3DDEVCAPS_SEPARATETEXTUREMEMORIES */
|
|
|
|
| D3DDEVCAPS_DRAWPRIMITIVES2EX
|
|
|
|
| D3DDEVCAPS_HWTRANSFORMANDLIGHT
|
|
|
|
| D3DDEVCAPS_CANBLTSYSTONONLOCAL
|
|
|
|
| D3DDEVCAPS_HWRASTERIZATION
|
|
|
|
| D3DDEVCAPS_PUREDEVICE
|
|
|
|
/* | D3DDEVCAPS_QUINTICRTPATCHES */
|
|
|
|
/* | D3DDEVCAPS_RTPATCHES */
|
|
|
|
/* | D3DDEVCAPS_RTPATCHHANDLEZERO */
|
|
|
|
/* | D3DDEVCAPS_NPATCHES */;
|
|
|
|
// Primitive Misc. Caps
|
|
|
|
pCaps->PrimitiveMiscCaps = D3DPMISCCAPS_MASKZ
|
|
|
|
| D3DPMISCCAPS_CULLNONE
|
|
|
|
| D3DPMISCCAPS_CULLCW
|
|
|
|
| D3DPMISCCAPS_CULLCCW
|
|
|
|
| D3DPMISCCAPS_COLORWRITEENABLE
|
|
|
|
| D3DPMISCCAPS_CLIPPLANESCALEDPOINTS
|
|
|
|
/* | D3DPMISCCAPS_CLIPTLVERTS */
|
|
|
|
| D3DPMISCCAPS_TSSARGTEMP
|
|
|
|
| D3DPMISCCAPS_BLENDOP
|
|
|
|
/* | D3DPMISCCAPS_NULLREFERENCE */
|
|
|
|
| D3DPMISCCAPS_INDEPENDENTWRITEMASKS
|
|
|
|
| D3DPMISCCAPS_PERSTAGECONSTANT
|
|
|
|
| D3DPMISCCAPS_FOGANDSPECULARALPHA
|
|
|
|
| D3DPMISCCAPS_SEPARATEALPHABLEND
|
|
|
|
| D3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
|
|
|
|
| D3DPMISCCAPS_MRTPOSTPIXELSHADERBLENDING
|
|
|
|
| D3DPMISCCAPS_FOGVERTEXCLAMPED
|
|
|
|
| D3DPMISCCAPS_POSTBLENDSRGBCONVERT;
|
|
|
|
// Raster Caps
|
|
|
|
pCaps->RasterCaps = D3DPRASTERCAPS_DITHER
|
|
|
|
| D3DPRASTERCAPS_ZTEST
|
|
|
|
| D3DPRASTERCAPS_FOGVERTEX
|
|
|
|
| D3DPRASTERCAPS_FOGTABLE
|
|
|
|
| D3DPRASTERCAPS_MIPMAPLODBIAS
|
|
|
|
/* | D3DPRASTERCAPS_ZBUFFERLESSHSR */
|
|
|
|
| D3DPRASTERCAPS_FOGRANGE
|
|
|
|
| D3DPRASTERCAPS_ANISOTROPY
|
|
|
|
/* | D3DPRASTERCAPS_WBUFFER */
|
|
|
|
| D3DPRASTERCAPS_WFOG
|
|
|
|
| D3DPRASTERCAPS_ZFOG
|
|
|
|
| D3DPRASTERCAPS_COLORPERSPECTIVE
|
|
|
|
| D3DPRASTERCAPS_SCISSORTEST
|
|
|
|
| D3DPRASTERCAPS_SLOPESCALEDEPTHBIAS
|
|
|
|
| D3DPRASTERCAPS_DEPTHBIAS
|
|
|
|
| D3DPRASTERCAPS_MULTISAMPLE_TOGGLE; // <-- TODO! (but difficult in Vk)
|
|
|
|
// Z Comparison Caps
|
|
|
|
pCaps->ZCmpCaps = D3DPCMPCAPS_NEVER
|
|
|
|
| D3DPCMPCAPS_LESS
|
|
|
|
| D3DPCMPCAPS_EQUAL
|
|
|
|
| D3DPCMPCAPS_LESSEQUAL
|
|
|
|
| D3DPCMPCAPS_GREATER
|
|
|
|
| D3DPCMPCAPS_NOTEQUAL
|
|
|
|
| D3DPCMPCAPS_GREATEREQUAL
|
|
|
|
| D3DPCMPCAPS_ALWAYS;
|
|
|
|
// Source Blend Caps
|
|
|
|
pCaps->SrcBlendCaps = D3DPBLENDCAPS_ZERO
|
|
|
|
| D3DPBLENDCAPS_ONE
|
|
|
|
| D3DPBLENDCAPS_SRCCOLOR
|
|
|
|
| D3DPBLENDCAPS_INVSRCCOLOR
|
|
|
|
| D3DPBLENDCAPS_SRCALPHA
|
|
|
|
| D3DPBLENDCAPS_INVSRCALPHA
|
|
|
|
| D3DPBLENDCAPS_DESTALPHA
|
|
|
|
| D3DPBLENDCAPS_INVDESTALPHA
|
|
|
|
| D3DPBLENDCAPS_DESTCOLOR
|
|
|
|
| D3DPBLENDCAPS_INVDESTCOLOR
|
|
|
|
| D3DPBLENDCAPS_SRCALPHASAT
|
|
|
|
| D3DPBLENDCAPS_BOTHSRCALPHA
|
|
|
|
| D3DPBLENDCAPS_BOTHINVSRCALPHA
|
|
|
|
| D3DPBLENDCAPS_BLENDFACTOR
|
|
|
|
| D3DPBLENDCAPS_INVSRCCOLOR2
|
|
|
|
| D3DPBLENDCAPS_SRCCOLOR2;
|
|
|
|
// Destination Blend Caps
|
|
|
|
pCaps->DestBlendCaps = pCaps->SrcBlendCaps;
|
|
|
|
// Alpha Comparison Caps
|
|
|
|
pCaps->AlphaCmpCaps = pCaps->ZCmpCaps;
|
|
|
|
// Shade Caps
|
|
|
|
pCaps->ShadeCaps = D3DPSHADECAPS_COLORGOURAUDRGB
|
|
|
|
| D3DPSHADECAPS_SPECULARGOURAUDRGB
|
|
|
|
| D3DPSHADECAPS_ALPHAGOURAUDBLEND
|
|
|
|
| D3DPSHADECAPS_FOGGOURAUD;
|
|
|
|
// Texture Caps
|
|
|
|
pCaps->TextureCaps = D3DPTEXTURECAPS_PERSPECTIVE
|
|
|
|
/* | D3DPTEXTURECAPS_POW2 */
|
|
|
|
| D3DPTEXTURECAPS_ALPHA
|
|
|
|
/* | D3DPTEXTURECAPS_SQUAREONLY */
|
|
|
|
| D3DPTEXTURECAPS_TEXREPEATNOTSCALEDBYSIZE
|
|
|
|
| D3DPTEXTURECAPS_ALPHAPALETTE
|
|
|
|
/* | D3DPTEXTURECAPS_NONPOW2CONDITIONAL */
|
|
|
|
| D3DPTEXTURECAPS_PROJECTED
|
|
|
|
| D3DPTEXTURECAPS_CUBEMAP
|
|
|
|
| D3DPTEXTURECAPS_VOLUMEMAP
|
|
|
|
| D3DPTEXTURECAPS_MIPMAP
|
|
|
|
| D3DPTEXTURECAPS_MIPVOLUMEMAP
|
|
|
|
| D3DPTEXTURECAPS_MIPCUBEMAP
|
|
|
|
/* | D3DPTEXTURECAPS_CUBEMAP_POW2 */
|
|
|
|
/* | D3DPTEXTURECAPS_VOLUMEMAP_POW2 */
|
|
|
|
/* | D3DPTEXTURECAPS_NOPROJECTEDBUMPENV */;
|
|
|
|
// Texture Filter Caps
|
|
|
|
pCaps->TextureFilterCaps = D3DPTFILTERCAPS_MINFPOINT
|
|
|
|
| D3DPTFILTERCAPS_MINFLINEAR
|
|
|
|
| D3DPTFILTERCAPS_MINFANISOTROPIC
|
|
|
|
/* | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD */
|
|
|
|
/* | D3DPTFILTERCAPS_MINFGAUSSIANQUAD */
|
|
|
|
| D3DPTFILTERCAPS_MIPFPOINT
|
|
|
|
| D3DPTFILTERCAPS_MIPFLINEAR
|
|
|
|
/* | D3DPTFILTERCAPS_CONVOLUTIONMONO */
|
|
|
|
| D3DPTFILTERCAPS_MAGFPOINT
|
|
|
|
| D3DPTFILTERCAPS_MAGFLINEAR
|
|
|
|
| D3DPTFILTERCAPS_MAGFANISOTROPIC
|
|
|
|
/* | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD */
|
|
|
|
/* | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD */;
|
|
|
|
// Cube Texture Filter Caps
|
|
|
|
pCaps->CubeTextureFilterCaps = pCaps->TextureFilterCaps;
|
|
|
|
// Volume Texture Filter Caps
|
|
|
|
pCaps->VolumeTextureFilterCaps = pCaps->TextureFilterCaps;
|
|
|
|
// Texture Address Caps
|
|
|
|
pCaps->TextureAddressCaps = D3DPTADDRESSCAPS_WRAP
|
|
|
|
| D3DPTADDRESSCAPS_MIRROR
|
|
|
|
| D3DPTADDRESSCAPS_CLAMP
|
|
|
|
| D3DPTADDRESSCAPS_BORDER
|
|
|
|
| D3DPTADDRESSCAPS_INDEPENDENTUV
|
|
|
|
| D3DPTADDRESSCAPS_MIRRORONCE;
|
|
|
|
// Volume Texture Address Caps
|
|
|
|
pCaps->VolumeTextureAddressCaps = pCaps->TextureAddressCaps;
|
|
|
|
// Line Caps
|
|
|
|
pCaps->LineCaps = D3DLINECAPS_TEXTURE
|
|
|
|
| D3DLINECAPS_ZTEST
|
|
|
|
| D3DLINECAPS_BLEND
|
|
|
|
| D3DLINECAPS_ALPHACMP
|
|
|
|
| D3DLINECAPS_FOG
|
|
|
|
| D3DLINECAPS_ANTIALIAS; //<-- Lying about doing AA lines here, we don't *fully* support that.
|
|
|
|
// Max Texture Width
|
|
|
|
pCaps->MaxTextureWidth = MaxTextureDimension;
|
|
|
|
// Max Texture Height
|
|
|
|
pCaps->MaxTextureHeight = MaxTextureDimension;
|
|
|
|
// Max Volume Extent
|
|
|
|
pCaps->MaxVolumeExtent = 8192;
|
|
|
|
// Max Texture Repeat
|
|
|
|
pCaps->MaxTextureRepeat = 8192;
|
|
|
|
// Max Texture Aspect Ratio
|
|
|
|
pCaps->MaxTextureAspectRatio = 8192;
|
|
|
|
// Max Anisotropy
|
|
|
|
pCaps->MaxAnisotropy = 16;
|
|
|
|
// Max Vertex W
|
|
|
|
pCaps->MaxVertexW = 1e10f;
|
|
|
|
// Guard Bands
|
|
|
|
pCaps->GuardBandLeft = -32768.0f;
|
|
|
|
pCaps->GuardBandTop = -32768.0f;
|
|
|
|
pCaps->GuardBandRight = 32768.0f;
|
|
|
|
pCaps->GuardBandBottom = 32768.0f;
|
|
|
|
// Extents Adjust
|
|
|
|
pCaps->ExtentsAdjust = 0.0f;
|
|
|
|
// Stencil Caps
|
|
|
|
pCaps->StencilCaps = D3DSTENCILCAPS_KEEP
|
|
|
|
| D3DSTENCILCAPS_ZERO
|
|
|
|
| D3DSTENCILCAPS_REPLACE
|
|
|
|
| D3DSTENCILCAPS_INCRSAT
|
|
|
|
| D3DSTENCILCAPS_DECRSAT
|
|
|
|
| D3DSTENCILCAPS_INVERT
|
|
|
|
| D3DSTENCILCAPS_INCR
|
|
|
|
| D3DSTENCILCAPS_DECR
|
|
|
|
| D3DSTENCILCAPS_TWOSIDED;
|
|
|
|
// FVF Caps
|
|
|
|
pCaps->FVFCaps = (MaxSimultaneousTextures & D3DFVFCAPS_TEXCOORDCOUNTMASK)
|
|
|
|
/* | D3DFVFCAPS_DONOTSTRIPELEMENTS */
|
|
|
|
| D3DFVFCAPS_PSIZE;
|
|
|
|
// Texture Op Caps
|
|
|
|
pCaps->TextureOpCaps = D3DTEXOPCAPS_DISABLE
|
|
|
|
| D3DTEXOPCAPS_SELECTARG1
|
|
|
|
| D3DTEXOPCAPS_SELECTARG2
|
|
|
|
| D3DTEXOPCAPS_MODULATE
|
|
|
|
| D3DTEXOPCAPS_MODULATE2X
|
|
|
|
| D3DTEXOPCAPS_MODULATE4X
|
|
|
|
| D3DTEXOPCAPS_ADD
|
|
|
|
| D3DTEXOPCAPS_ADDSIGNED
|
|
|
|
| D3DTEXOPCAPS_ADDSIGNED2X
|
|
|
|
| D3DTEXOPCAPS_SUBTRACT
|
|
|
|
| D3DTEXOPCAPS_ADDSMOOTH
|
|
|
|
| D3DTEXOPCAPS_BLENDDIFFUSEALPHA
|
|
|
|
| D3DTEXOPCAPS_BLENDTEXTUREALPHA
|
|
|
|
| D3DTEXOPCAPS_BLENDFACTORALPHA
|
|
|
|
| D3DTEXOPCAPS_BLENDTEXTUREALPHAPM
|
|
|
|
| D3DTEXOPCAPS_BLENDCURRENTALPHA
|
|
|
|
| D3DTEXOPCAPS_PREMODULATE
|
|
|
|
| D3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
|
|
|
|
| D3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
|
|
|
|
| D3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
|
|
|
|
| D3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA
|
|
|
|
| D3DTEXOPCAPS_BUMPENVMAP
|
|
|
|
| D3DTEXOPCAPS_BUMPENVMAPLUMINANCE
|
|
|
|
| D3DTEXOPCAPS_DOTPRODUCT3
|
|
|
|
| D3DTEXOPCAPS_MULTIPLYADD
|
|
|
|
| D3DTEXOPCAPS_LERP;
|
|
|
|
// Max Texture Blend Stages
|
|
|
|
pCaps->MaxTextureBlendStages = MaxTextureBlendStages;
|
|
|
|
// Max Simultaneous Textures
|
|
|
|
pCaps->MaxSimultaneousTextures = MaxSimultaneousTextures;
|
|
|
|
// Vertex Processing Caps
|
|
|
|
pCaps->VertexProcessingCaps = D3DVTXPCAPS_TEXGEN
|
|
|
|
| D3DVTXPCAPS_MATERIALSOURCE7
|
|
|
|
| D3DVTXPCAPS_DIRECTIONALLIGHTS
|
|
|
|
| D3DVTXPCAPS_POSITIONALLIGHTS
|
|
|
|
| D3DVTXPCAPS_LOCALVIEWER
|
|
|
|
| D3DVTXPCAPS_TWEENING
|
|
|
|
| D3DVTXPCAPS_TEXGEN_SPHEREMAP
|
|
|
|
/* | D3DVTXPCAPS_NO_TEXGEN_NONLOCALVIEWER*/;
|
|
|
|
// Max Active Lights
|
|
|
|
pCaps->MaxActiveLights = caps::MaxEnabledLights;
|
|
|
|
// Max User Clip Planes
|
|
|
|
pCaps->MaxUserClipPlanes = MaxClipPlanes;
|
|
|
|
// Max Vertex Blend Matrices
|
|
|
|
pCaps->MaxVertexBlendMatrices = 4;
|
|
|
|
// Max Vertex Blend Matrix Index
|
|
|
|
pCaps->MaxVertexBlendMatrixIndex = 8;
|
|
|
|
// Max Point Size
|
|
|
|
pCaps->MaxPointSize = 256.0f;
|
|
|
|
// Max Primitive Count
|
|
|
|
pCaps->MaxPrimitiveCount = 0x00555555;
|
|
|
|
// Max Vertex Index
|
|
|
|
pCaps->MaxVertexIndex = 0x00ffffff;
|
|
|
|
// Max Streams
|
|
|
|
pCaps->MaxStreams = MaxStreams;
|
|
|
|
// Max Stream Stride
|
|
|
|
pCaps->MaxStreamStride = 508; // bytes
|
|
|
|
|
|
|
|
const uint32_t majorVersion = options.shaderModel;
|
|
|
|
const uint32_t minorVersion = options.shaderModel != 1 ? 0 : 4;
|
|
|
|
|
|
|
|
// Shader Versions
|
|
|
|
pCaps->VertexShaderVersion = D3DVS_VERSION(majorVersion, minorVersion);
|
|
|
|
pCaps->PixelShaderVersion = D3DPS_VERSION(majorVersion, minorVersion);
|
|
|
|
|
|
|
|
// Max Vertex Shader Const
|
|
|
|
pCaps->MaxVertexShaderConst = MaxFloatConstantsVS;
|
|
|
|
// Max PS1 Value
|
|
|
|
pCaps->PixelShader1xMaxValue = FLT_MAX;
|
|
|
|
// Dev Caps 2
|
|
|
|
pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET
|
|
|
|
/* | D3DDEVCAPS2_DMAPNPATCH */
|
|
|
|
/* | D3DDEVCAPS2_ADAPTIVETESSRTPATCH */
|
|
|
|
/* | D3DDEVCAPS2_ADAPTIVETESSNPATCH */
|
|
|
|
| D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES
|
|
|
|
/* | D3DDEVCAPS2_PRESAMPLEDDMAPNPATCH */
|
|
|
|
| D3DDEVCAPS2_VERTEXELEMENTSCANSHARESTREAMOFFSET;
|
|
|
|
// Max N Patch Tesselation Level
|
|
|
|
pCaps->MaxNpatchTessellationLevel = 0.0f;
|
|
|
|
// Reserved for... something
|
|
|
|
pCaps->Reserved5 = 0;
|
|
|
|
// Master adapter for us is adapter 0, atm...
|
|
|
|
pCaps->MasterAdapterOrdinal = 0;
|
|
|
|
// The group of adapters this one is in
|
|
|
|
pCaps->AdapterOrdinalInGroup = 0;
|
|
|
|
// Number of adapters in current group
|
|
|
|
pCaps->NumberOfAdaptersInGroup = 1;
|
|
|
|
// Decl Type Caps
|
|
|
|
pCaps->DeclTypes = D3DDTCAPS_UBYTE4
|
|
|
|
| D3DDTCAPS_UBYTE4N
|
|
|
|
| D3DDTCAPS_SHORT2N
|
|
|
|
| D3DDTCAPS_SHORT4N
|
|
|
|
| D3DDTCAPS_USHORT2N
|
|
|
|
| D3DDTCAPS_USHORT4N
|
|
|
|
| D3DDTCAPS_UDEC3
|
|
|
|
| D3DDTCAPS_DEC3N
|
|
|
|
| D3DDTCAPS_FLOAT16_2
|
|
|
|
| D3DDTCAPS_FLOAT16_4;
|
|
|
|
// Number of simultaneous RTs
|
|
|
|
pCaps->NumSimultaneousRTs = MaxSimultaneousRenderTargets;
|
|
|
|
// Possible StretchRect filters
|
|
|
|
pCaps->StretchRectFilterCaps = D3DPTFILTERCAPS_MINFPOINT
|
|
|
|
| D3DPTFILTERCAPS_MINFLINEAR
|
|
|
|
/* | D3DPTFILTERCAPS_MINFANISOTROPIC */
|
|
|
|
/* | D3DPTFILTERCAPS_MINFPYRAMIDALQUAD */
|
|
|
|
/* | D3DPTFILTERCAPS_MINFGAUSSIANQUAD */
|
|
|
|
/* | D3DPTFILTERCAPS_MIPFPOINT */
|
|
|
|
/* | D3DPTFILTERCAPS_MIPFLINEAR */
|
|
|
|
/* | D3DPTFILTERCAPS_CONVOLUTIONMONO */
|
|
|
|
| D3DPTFILTERCAPS_MAGFPOINT
|
|
|
|
| D3DPTFILTERCAPS_MAGFLINEAR
|
|
|
|
/* | D3DPTFILTERCAPS_MAGFANISOTROPIC */
|
|
|
|
/* | D3DPTFILTERCAPS_MAGFPYRAMIDALQUAD */
|
|
|
|
/* | D3DPTFILTERCAPS_MAGFGAUSSIANQUAD */;
|
|
|
|
|
|
|
|
// Not too bothered about doing these longhand
|
|
|
|
// We should match whatever my AMD hardware reports here
|
|
|
|
// methinks for the best chance of stuff working.
|
|
|
|
pCaps->VS20Caps.Caps = 1;
|
|
|
|
pCaps->VS20Caps.DynamicFlowControlDepth = 24;
|
|
|
|
pCaps->VS20Caps.NumTemps = 32;
|
|
|
|
pCaps->VS20Caps.StaticFlowControlDepth = 4;
|
|
|
|
|
|
|
|
pCaps->PS20Caps.Caps = 31;
|
|
|
|
pCaps->PS20Caps.DynamicFlowControlDepth = 24;
|
|
|
|
pCaps->PS20Caps.NumTemps = 32;
|
|
|
|
pCaps->PS20Caps.StaticFlowControlDepth = 4;
|
|
|
|
|
|
|
|
pCaps->PS20Caps.NumInstructionSlots = options.shaderModel >= 2 ? 512 : 256;
|
|
|
|
|
|
|
|
pCaps->VertexTextureFilterCaps = 50332416;
|
|
|
|
pCaps->MaxVShaderInstructionsExecuted = 4294967295;
|
|
|
|
pCaps->MaxPShaderInstructionsExecuted = 4294967295;
|
|
|
|
|
|
|
|
pCaps->MaxVertexShader30InstructionSlots = options.shaderModel == 3 ? 32768 : 0;
|
|
|
|
pCaps->MaxPixelShader30InstructionSlots = options.shaderModel == 3 ? 32768 : 0;
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HMONITOR D3D9Adapter::GetMonitor() {
|
|
|
|
return GetDefaultMonitor();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UINT D3D9Adapter::GetAdapterModeCountEx(CONST D3DDISPLAYMODEFILTER* pFilter) {
|
|
|
|
if (pFilter == nullptr)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
// We don't offer any interlaced formats here so early out and avoid destroying mode cache.
|
|
|
|
if (pFilter->ScanLineOrdering == D3DSCANLINEORDERING_INTERLACED)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
CacheModes(EnumerateFormat(pFilter->Format));
|
|
|
|
return m_modes.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::EnumAdapterModesEx(
|
|
|
|
const D3DDISPLAYMODEFILTER* pFilter,
|
|
|
|
UINT Mode,
|
|
|
|
D3DDISPLAYMODEEX* pMode) {
|
|
|
|
if (pMode == nullptr || pFilter == nullptr)
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
const D3D9Format format =
|
|
|
|
EnumerateFormat(pFilter->Format);
|
|
|
|
|
|
|
|
if (FAILED(CheckDeviceFormat(
|
|
|
|
D3DDEVTYPE_HAL, EnumerateFormat(pFilter->Format),
|
|
|
|
D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE,
|
|
|
|
EnumerateFormat(pFilter->Format))))
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
CacheModes(format);
|
|
|
|
|
|
|
|
// We don't return any scanline orderings that aren't progressive,
|
|
|
|
// The format filtering is already handled for us by cache modes
|
|
|
|
// So we can early out here and then just index.
|
|
|
|
if (pFilter->ScanLineOrdering == D3DSCANLINEORDERING_INTERLACED)
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
if (Mode >= m_modes.size())
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
*pMode = m_modes[Mode];
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::GetAdapterDisplayModeEx(
|
|
|
|
D3DDISPLAYMODEEX* pMode,
|
|
|
|
D3DDISPLAYROTATION* pRotation) {
|
2020-01-06 05:06:45 +01:00
|
|
|
if (pMode == nullptr)
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
2019-12-16 04:28:01 +01:00
|
|
|
if (pRotation != nullptr)
|
|
|
|
*pRotation = D3DDISPLAYROTATION_IDENTITY;
|
|
|
|
|
2020-01-06 05:06:45 +01:00
|
|
|
MONITORINFOEXW monInfo = { };
|
|
|
|
monInfo.cbSize = sizeof(monInfo);
|
|
|
|
|
|
|
|
if (!::GetMonitorInfoW(GetDefaultMonitor(), reinterpret_cast<MONITORINFO*>(&monInfo)))
|
|
|
|
throw DxvkError("D3D9Adapter::GetAdapterDisplayModeEx: Failed to query monitor info");
|
|
|
|
|
|
|
|
DEVMODEW devMode = DEVMODEW();
|
|
|
|
devMode.dmSize = sizeof(devMode);
|
2019-12-16 04:28:01 +01:00
|
|
|
|
2020-01-06 05:06:45 +01:00
|
|
|
if (!::EnumDisplaySettingsW(monInfo.szDevice, ENUM_CURRENT_SETTINGS, &devMode)) {
|
|
|
|
Logger::err("D3D9Adapter::GetAdapterDisplayModeEx: Failed to enum display settings");
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pMode->Size = sizeof(D3DDISPLAYMODEEX);
|
|
|
|
pMode->Width = devMode.dmPelsWidth;
|
|
|
|
pMode->Height = devMode.dmPelsHeight;
|
|
|
|
pMode->RefreshRate = devMode.dmDisplayFrequency;
|
|
|
|
pMode->Format = D3DFMT_X8R8G8B8;
|
|
|
|
pMode->ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE;
|
|
|
|
|
|
|
|
return D3D_OK;
|
2019-12-16 04:28:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::GetAdapterLUID(LUID* pLUID) {
|
|
|
|
if (pLUID == nullptr)
|
|
|
|
return D3DERR_INVALIDCALL;
|
|
|
|
|
|
|
|
auto& deviceId = m_adapter->devicePropertiesExt().coreDeviceId;
|
|
|
|
|
|
|
|
if (deviceId.deviceLUIDValid)
|
|
|
|
*pLUID = bit::cast<LUID>(deviceId.deviceLUID);
|
|
|
|
else
|
|
|
|
*pLUID = dxvk::GetAdapterLUID(m_ordinal);
|
|
|
|
|
|
|
|
return D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
HRESULT D3D9Adapter::CheckDeviceVkFormat(
|
|
|
|
VkFormat Format,
|
|
|
|
DWORD Usage,
|
|
|
|
D3DRESOURCETYPE RType) {
|
|
|
|
VkFormatFeatureFlags checkFlags = 0;
|
|
|
|
|
|
|
|
if (RType != D3DRTYPE_SURFACE)
|
|
|
|
checkFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
|
|
|
|
|
|
|
if (Usage & D3DUSAGE_RENDERTARGET) {
|
|
|
|
checkFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
|
|
|
|
|
|
|
if (Usage & D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING)
|
|
|
|
checkFlags |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Usage & D3DUSAGE_DEPTHSTENCIL)
|
|
|
|
checkFlags |= VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
|
|
|
|
else
|
|
|
|
checkFlags |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
|
|
|
|
|
|
|
VkFormatFeatureFlags checkFlagsMipGen = checkFlags;
|
|
|
|
|
|
|
|
if (Usage & D3DUSAGE_AUTOGENMIPMAP) {
|
|
|
|
checkFlagsMipGen |= VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
|
|
|
|
checkFlagsMipGen |= VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;
|
|
|
|
}
|
|
|
|
|
|
|
|
VkFormatProperties fmtSupport = m_adapter->formatProperties(Format);
|
|
|
|
VkFormatFeatureFlags imgFeatures = fmtSupport.optimalTilingFeatures | fmtSupport.linearTilingFeatures;
|
|
|
|
|
|
|
|
if ((imgFeatures & checkFlags) != checkFlags)
|
|
|
|
return D3DERR_NOTAVAILABLE;
|
|
|
|
|
|
|
|
return ((imgFeatures & checkFlagsMipGen) != checkFlagsMipGen)
|
|
|
|
? D3DOK_NOAUTOGEN
|
|
|
|
: D3D_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void D3D9Adapter::CacheModes(D3D9Format Format) {
|
|
|
|
if (!m_modes.empty() && m_modeCacheFormat == Format)
|
|
|
|
return; // We already cached the modes for this format. No need to do it again.
|
|
|
|
|
|
|
|
::MONITORINFOEXW monInfo;
|
|
|
|
monInfo.cbSize = sizeof(monInfo);
|
|
|
|
|
|
|
|
if (!::GetMonitorInfoW(GetDefaultMonitor(), reinterpret_cast<MONITORINFO*>(&monInfo))) {
|
|
|
|
Logger::err("D3D9Adapter::CacheModes: failed to query monitor info");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_modes.clear();
|
|
|
|
m_modeCacheFormat = Format;
|
|
|
|
|
|
|
|
// Skip unsupported formats
|
2020-02-14 01:46:02 +01:00
|
|
|
if (!IsSupportedAdapterFormat(Format, false))
|
2019-12-16 04:28:01 +01:00
|
|
|
return;
|
|
|
|
|
|
|
|
auto& options = m_parent->GetOptions();
|
|
|
|
|
|
|
|
// Walk over all modes that the display supports and
|
|
|
|
// return those that match the requested format etc.
|
|
|
|
DEVMODEW devMode = { };
|
|
|
|
devMode.dmSize = sizeof(DEVMODEW);
|
|
|
|
|
|
|
|
uint32_t modeIndex = 0;
|
|
|
|
|
|
|
|
const auto forcedRatio = Ratio<DWORD>(options.forceAspectRatio);
|
|
|
|
|
|
|
|
while (::EnumDisplaySettingsW(monInfo.szDevice, modeIndex++, &devMode)) {
|
|
|
|
// Skip interlaced modes altogether
|
|
|
|
if (devMode.dmDisplayFlags & DM_INTERLACED)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Skip modes with incompatible formats
|
|
|
|
if (devMode.dmBitsPerPel != GetMonitorFormatBpp(Format))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
if (!forcedRatio.undefined() && Ratio<DWORD>(devMode.dmPelsWidth, devMode.dmPelsHeight) != forcedRatio)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
D3DDISPLAYMODEEX mode;
|
|
|
|
mode.Size = sizeof(D3DDISPLAYMODEEX);
|
|
|
|
mode.Width = devMode.dmPelsWidth;
|
|
|
|
mode.Height = devMode.dmPelsHeight;
|
|
|
|
mode.RefreshRate = devMode.dmDisplayFrequency;
|
|
|
|
mode.Format = static_cast<D3DFORMAT>(Format);
|
|
|
|
mode.ScanLineOrdering = D3DSCANLINEORDERING_PROGRESSIVE;
|
|
|
|
|
|
|
|
m_modes.push_back(mode);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort display modes by width, height and refresh rate,
|
|
|
|
// in that order. Some games rely on correct ordering.
|
|
|
|
std::sort(m_modes.begin(), m_modes.end(),
|
|
|
|
[](const D3DDISPLAYMODEEX & a, const D3DDISPLAYMODEEX & b) {
|
|
|
|
if (a.Width < b.Width) return true;
|
|
|
|
if (a.Width > b.Width) return false;
|
|
|
|
|
|
|
|
if (a.Height < b.Height) return true;
|
|
|
|
if (a.Height > b.Height) return false;
|
|
|
|
|
|
|
|
return a.RefreshRate < b.RefreshRate;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|