1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-07 16:54:14 +01:00

[d3d8/9] Proper (and age accurate) handling of d3d9.shaderModel = 0

This commit is contained in:
WinterSnowfall 2025-01-21 01:31:59 +02:00 committed by Robin Kertels
parent 48d24893d4
commit c6dc7e0939
13 changed files with 63 additions and 27 deletions

View File

@ -464,6 +464,7 @@
# capabilities that the applicatation queries.
#
# Supported values:
# - 0: Fixed-function only
# - 1: Shader Model 1
# - 2: Shader Model 2
# - 3: Shader Model 3

View File

@ -19,7 +19,10 @@ namespace dxvk {
// Max supported shader model is PS 1.4 and VS 1.1
pCaps8->VertexShaderVersion = D3DVS_VERSION(1, 1);
pCaps8->PixelShaderVersion = D3DPS_VERSION(1, 4);
// Late fixed-function capable hardware will advertise VS 1.1
// support, but will not advertise any support for PS
if (likely(caps9.PixelShaderVersion != D3DPS_VERSION(0, 0)))
pCaps8->PixelShaderVersion = D3DPS_VERSION(1, 4);
// Remove D3D9-specific caps:

View File

@ -58,6 +58,12 @@ namespace dxvk {
if (m_d3d8Options.batching)
m_batcher = new D3D8Batcher(this, GetD3D9());
d3d9::D3DCAPS9 caps9;
HRESULT res = GetD3D9()->GetDeviceCaps(&caps9);
if (unlikely(SUCCEEDED(res) && caps9.PixelShaderVersion == D3DPS_VERSION(0, 0)))
m_isFixedFunctionOnly = true;
}
D3D8Device::~D3D8Device() {
@ -1784,8 +1790,8 @@ namespace dxvk {
// Validate VS version for non-FF shaders
if (pFunction != nullptr) {
uint32_t majorVersion = (pFunction[0] >> 8) & 0xff;
uint32_t minorVersion = pFunction[0] & 0xff;
const uint32_t majorVersion = (pFunction[0] >> 8) & 0xff;
const uint32_t minorVersion = pFunction[0] & 0xff;
if (unlikely(majorVersion != 1 || minorVersion > 1)) {
Logger::err(str::format("D3D8Device::CreateVertexShader: Unsupported VS version ", majorVersion, ".", minorVersion));
@ -2023,10 +2029,10 @@ namespace dxvk {
if (unlikely(pFunction == nullptr || pHandle == nullptr))
return D3DERR_INVALIDCALL;
uint32_t majorVersion = (pFunction[0] >> 8) & 0xff;
uint32_t minorVersion = pFunction[0] & 0xff;
const uint32_t majorVersion = (pFunction[0] >> 8) & 0xff;
const uint32_t minorVersion = pFunction[0] & 0xff;
if (unlikely(majorVersion != 1 || minorVersion > 4)) {
if (unlikely(m_isFixedFunctionOnly || majorVersion != 1 || minorVersion > 4)) {
Logger::err(str::format("D3D8Device::CreatePixelShader: Unsupported PS version ", majorVersion, ".", minorVersion));
return D3DERR_INVALIDCALL;
}

View File

@ -429,6 +429,9 @@ namespace dxvk {
// Value of D3DRS_PATCHSEGMENTS
float m_patchSegments = 1.0f;
// Controls fixed-function exclusive mode (no PS support)
bool m_isFixedFunctionOnly = false;
D3D8StateBlock* m_recorder = nullptr;
DWORD m_recorderToken = 0;
DWORD m_token = 0;

View File

@ -12,7 +12,7 @@ namespace dxvk {
// Get the bridge interface to D3D9.
if (FAILED(m_d3d9->QueryInterface(__uuidof(IDxvkD3D8InterfaceBridge), (void**)&m_bridge))) {
throw DxvkError("D3D8Device: ERROR! Failed to get D3D9 Bridge. d3d9.dll might not be DXVK!");
throw DxvkError("D3D8Interface: ERROR! Failed to get D3D9 Bridge. d3d9.dll might not be DXVK!");
}
m_bridge->SetD3D8CompatibilityMode(true);

View File

@ -26,8 +26,8 @@ extern "C" {
if (unlikely(pPixelShader == nullptr)) {
errorMessage = "D3D8: ValidatePixelShader: Null pPixelShader";
} else {
uint32_t majorVersion = (pPixelShader[0] >> 8) & 0xff;
uint32_t minorVersion = pPixelShader[0] & 0xff;
const uint32_t majorVersion = (pPixelShader[0] >> 8) & 0xff;
const uint32_t minorVersion = pPixelShader[0] & 0xff;
if (unlikely(majorVersion != 1 || minorVersion > 4)) {
errorMessage = dxvk::str::format("D3D8: ValidatePixelShader: Unsupported PS version ",
@ -69,8 +69,8 @@ extern "C" {
if (unlikely(pVertexShader == nullptr)) {
errorMessage = "D3D8: ValidateVertexShader: Null pVertexShader";
} else {
uint32_t majorVersion = (pVertexShader[0] >> 8) & 0xff;
uint32_t minorVersion = pVertexShader[0] & 0xff;
const uint32_t majorVersion = (pVertexShader[0] >> 8) & 0xff;
const uint32_t minorVersion = pVertexShader[0] & 0xff;
if (unlikely(majorVersion != 1 || minorVersion > 1)) {
errorMessage = dxvk::str::format("D3D8: ValidateVertexShader: Unsupported VS version ",

View File

@ -573,17 +573,22 @@ namespace dxvk {
// Max Stream Stride
pCaps->MaxStreamStride = 508; // bytes
const uint32_t majorVersion = options.shaderModel;
const uint32_t minorVersion = options.shaderModel != 1 ? 0 : 4;
// Late fixed-function capable cards, such as the GeForce 4 MX series,
// expose support for VS 1.1, while not advertising any PS support
const uint32_t majorVersionVS = options.shaderModel == 0 ? 1 : options.shaderModel;
const uint32_t majorVersionPS = options.shaderModel;
// Max supported SM1 is VS 1.1 and PS 1.4
const uint32_t minorVersionVS = majorVersionVS != 1 ? 0 : 1;
const uint32_t minorVersionPS = majorVersionPS != 1 ? 0 : 4;
// Shader Versions
pCaps->VertexShaderVersion = D3DVS_VERSION(majorVersion, minorVersion);
pCaps->PixelShaderVersion = D3DPS_VERSION(majorVersion, minorVersion);
pCaps->VertexShaderVersion = D3DVS_VERSION(majorVersionVS, minorVersionVS);
pCaps->PixelShaderVersion = D3DPS_VERSION(majorVersionPS, minorVersionPS);
// Max Vertex Shader Const
pCaps->MaxVertexShaderConst = MaxFloatConstantsVS;
// Max PS1 Value
pCaps->PixelShader1xMaxValue = FLT_MAX;
pCaps->PixelShader1xMaxValue = options.shaderModel > 0 ? FLT_MAX : 0.0f;
// Dev Caps 2
pCaps->DevCaps2 = D3DDEVCAPS2_STREAMOFFSET
/* | D3DDEVCAPS2_DMAPNPATCH */
@ -646,8 +651,8 @@ namespace dxvk {
pCaps->PS20Caps.NumInstructionSlots = options.shaderModel >= 2 ? 512 : 256;
pCaps->VertexTextureFilterCaps = 50332416;
pCaps->MaxVShaderInstructionsExecuted = 4294967295;
pCaps->MaxPShaderInstructionsExecuted = 4294967295;
pCaps->MaxVShaderInstructionsExecuted = options.shaderModel >= 2 ? 4294967295 : 0;
pCaps->MaxPShaderInstructionsExecuted = options.shaderModel >= 2 ? 4294967295 : 0;
pCaps->MaxVertexShader30InstructionSlots = options.shaderModel == 3 ? 32768 : 0;
pCaps->MaxPixelShader30InstructionSlots = options.shaderModel == 3 ? 32768 : 0;

View File

@ -3314,6 +3314,19 @@ namespace dxvk {
if (unlikely(ppShader == nullptr))
return D3DERR_INVALIDCALL;
const uint32_t majorVersion = (pFunction[0] >> 8) & 0xff;
const uint32_t minorVersion = pFunction[0] & 0xff;
// Late fixed-function capable hardware exposed support for VS 1.1
const uint32_t shaderModelVS = m_d3d9Options.shaderModel == 0 ? 1 : m_d3d9Options.shaderModel;
if (unlikely(majorVersion > shaderModelVS
|| (majorVersion == 1 && minorVersion > 1)
|| (majorVersion > 1 && minorVersion != 0))) {
Logger::err(str::format("D3D9DeviceEx::CreateVertexShader: Unsupported VS version ", majorVersion, ".", minorVersion));
return D3DERR_INVALIDCALL;
}
DxsoModuleInfo moduleInfo;
moduleInfo.options = m_dxsoOptions;
@ -3678,6 +3691,16 @@ namespace dxvk {
if (unlikely(ppShader == nullptr))
return D3DERR_INVALIDCALL;
const uint32_t majorVersion = (pFunction[0] >> 8) & 0xff;
const uint32_t minorVersion = pFunction[0] & 0xff;
if (unlikely(majorVersion > m_d3d9Options.shaderModel
|| (majorVersion == 1 && minorVersion > 4)
|| (majorVersion > 1 && minorVersion != 0))) {
Logger::err(str::format("D3D9DeviceEx::CreatePixelShader: Unsupported PS version ", majorVersion, ".", minorVersion));
return D3DERR_INVALIDCALL;
}
DxsoModuleInfo moduleInfo;
moduleInfo.options = m_dxsoOptions;

View File

@ -67,6 +67,9 @@ namespace dxvk {
SetProcessDPIAware();
}
#endif
if (unlikely(m_d3d9Options.shaderModel == 0))
Logger::warn("D3D9InterfaceEx: WARNING! Fixed-function exclusive mode is enabled.");
}

View File

@ -34,7 +34,7 @@ namespace dxvk {
int32_t maxFrameRate;
/// Set the max shader model the device can support in the caps.
int32_t shaderModel;
uint32_t shaderModel;
/// Whether or not to set the process as DPI aware in Windows when the API interface is created.
bool dpiAware;

View File

@ -98,9 +98,6 @@ namespace dxvk {
DxsoModule module(reader);
if (module.info().majorVersion() > pDxbcModuleInfo->options.shaderModel)
throw DxvkError("GetShaderModule: Out of range of supported shader model");
if (module.info().shaderStage() != ShaderStage)
throw DxvkError("GetShaderModule: Bytecode does not match shader stage");

View File

@ -20,8 +20,6 @@ namespace dxvk {
strictPow = options.strictPow;
d3d9FloatEmulation = options.d3d9FloatEmulation;
shaderModel = options.shaderModel;
invariantPosition = options.invariantPosition;
forceSamplerTypeSpecConstants = options.forceSamplerTypeSpecConstants;

View File

@ -25,9 +25,6 @@ namespace dxvk {
/// Whether or not we should care about pow(0, 0) = 1
bool strictPow;
/// Max version of shader to support
uint32_t shaderModel;
/// Work around a NV driver quirk
/// Fixes flickering/z-fighting in some games.
bool invariantPosition;