For games that use d3dim.dll, how can I check which exact version of Direct3D is used?

I had it wrong all along; spent days testing dozens of games without realizing it.
I've been trying to clean them up, starting with D3D8.
That's surely a momentous task, but what's the actual point of this investigation, considering that dgVoodoo2 emulation is doing very well?

I'd imagine this information is only required if you need to build a retro PC with 15 year old components from late 2000s and run that specific software in an actual installation of Windows XP; and maybe 25 year old parts from early 2000s to run it in an actual installation of Windows 9x/ME...

there are quite a few games that require or come with DirectX 8 or 8.1 installers, and yet do not even touch d3d8.dll.
Well, the DirectX 8.1b redistributable package does incorporate all the previously released DirectX runtimes for Windows95/98/ME and Windows 2000/XP, so game developers just shipped the most recent redistributable package from the latest DirectX SDK.

Since Windows Vista, DirectX has become the OS component and the driver model has changed to WDDM/DXGK, so major changes like the new DirectX/DXGI version would only ship as an OS update, and the redistributable DirectX package only contains the updated D3DCompiler.

all D3D2-6 games will request the same IID_IDirect3D3 interface. As you've wrtitten above one should look at what devices are being created/initialized after that to figure out which specific D3D version is being used.

Did you mean IDrect3D/IDirect3DDevice? Because iDrect3D3/IDirect3DDevice3 interfaces are from the DirectX SDK 6.0.


Again, Direct3D applications would only query for an interface when they really need to use methods available from that specific interface, i.e. multitexturing and vertex buffers from a Direct3D 6.0 device. While it is technically possible to first create IDrect3DDevice rendering device, then query it for IDrect3DDevice2 or IDrect3DDevice3 interfaces - or vice versa, create IDrect3DDevice3 device, then query for IDrect3DDevice2 interface (except for IDrect3DDevice7, which doesn't inherit from any of the legacy interfaces), it is pointless to query for a specific interface when you do not intend to use rendering methods provided by that inerface.


Imagine I would request a IDrect3DDevice2 (Direct3D 5.0) interface, so I could use IDrect3DDevice2::SetRenderTarget and IDrect3DDevice2::DrawPrimitive, but the user only has Direct3D 3.0 runtime installed, so my query will result in an error.

Then I have to either fall back to IDrect3DDevice and IDrect3DDevice::Execute some ExecuteBuffers, or throw an error and make the user install the DirectX 5.0 redistributable package (and probably buy a better videocard that supports the DrawPrimitive DDI).

If this user has the DirectX 6.0 runtime installed, then my query for IDrect3DDevice2 will also succeed. And if the user has a compliant Direct3D 6.0 video card which supports multitexturing, I could also query for iDrect3DDevice3 (to use multitexturing capabilities without having to fall back to multi-pass rendering) and it will succeed as well.



FYI, IID is "interface identifier", similar to CLSID for a COM class. This is a private variable containing an unique identifier (a 128-bit Microsoft GUID). The "interface" would be IDrect3D/IDirect3DDevice, i.e. the the entire COM class complete with public member functions (COM "methods") and private variables. DirectX uses "lightweight COM" model, so it consistently implements IUnknown interface and the QueryInterface method, which looks for a matching IID among all of its inherited interfaces. Since IDrect3D3 (Direct3D 6.0) interface does inherit from iDrect3D2 (Direct3D 5.0) interface and iDrect3D(Direct3D 2.0/3.0) interface, it is possible to create one device type and then query it with an interface ID to a different device type.
 
Did you mean IDrect3D/IDirect3DDevice? Because iDrect3D3/IDirect3DDevice3 interfaces are from the DirectX SDK 6.0.
Yeah, you're right, I haven't been paying attention =)

Again, Direct3D applications would only query for an interface when they really need to use methods available from that specific interface, i.e. multitexturing and vertex buffers from a Direct3D 6.0 device. While it is technically possible to first create IDrect3DDevice rendering device, then query it for IDrect3DDevice2 or IDrect3DDevice3 interfaces - or vice versa, create IDrect3DDevice3 device, then query for IDrect3DDevice2 interface (except for IDrect3DDevice7, which doesn't inherit from any of the legacy interfaces), it is pointless to query for a specific interface when you do not intend to use rendering methods provided by that inerface.
That being said many older games do just that it seems - query some DD 5.0 and then proceed to use functions from DD 1.0 only ¯\_(ツ)_/¯
 
That's surely a momentous task, but what's the actual point of this investigation, considering that dgVoodoo2 emulation is doing very well?

I'd imagine this information is only required if you need to build a retro PC with 15 year old components from late 2000s and run that specific software in an actual installation of Windows XP; and maybe 25 year old parts from early 2000s to run it in an actual installation of Windows 9x/ME...

It's not good for such a wiki which focuses on technical details and game fixes to have false information.

It all started with trying to run older games under XP in VMware. I had noticed that only D3D9 is accelerated properly; D3D8 is mostly ok with some visual and performance issues, but D3D7 and older are most of the time broken.
I thought perhaps a wrapper would help. dgvoodoo2 does not support XP, and there's no compatible D3D2-7 to 9 wrapper, however for D3D8 I could use d3d8to9.

I then looked at the Direct3D 8 games list on pcgamingwiki, and tried a few with d3d8to9, but they didn't work; no wrapping. That's when I started to check which D3D version a game actually uses and quickly noticed a LOT of the listed games weren't D3D8 at all. The same issue with older lists. Quite a few DDraw-only games are also wrongly listed as Direct3D.

It took a lot of convincing (as mentioned before) to change things, one of them being renaming the list names from DirectX to Direct3D.

Well, the DirectX 8.1b redistributable package does incorporate all the previously released DirectX runtimes for Windows95/98/ME and Windows 2000/XP, so game developers just shipped the most recent redistributable package from the latest DirectX SDK.

Since Windows Vista, DirectX has become the OS component and the driver model has changed to WDDM/DXGK, so major changes like the new DirectX/DXGI version would only ship as an OS update, and the redistributable DirectX package only contains the updated D3DCompiler.

Exactly, all older D3D files are included. Besides, there are many other APIs included too, like DirectInput, DirectSound, etc. There are games that require DirectX 8 but only use, say, the updated DirectInput from the package. One of the members was quite defensive and annoyed about it. Kept saying "Well, if it doesn't use D3D8 then it's not a DX8 game". Well, it is, just doesn't use the corresponding D3D file. There are even OpenGL games that require DirectX.

It was probably because he had edited hundreds of games' Direct3D fields with no testing, and they turned out to be wrong. The fault was with pcgamingwiki's rules though, which allowed populating the field simply based on the DX version.
 
Last edited:
There are even OpenGL games that require DirectX.
That's because DirectX isn't just Direct3D while Direct3D has been distributed as one package up until they switched to distributing it through the OS updates with DX10.
So a game which require DirectX 9 may require it for sound or input for example but use D3D8 from that same DirectX 9 "redistributable" for rendering.
 
Uuu, yea, that's what I wrote in my post.
You've wrote that they've "renamed the list names from DirectX to Direct3D". This isn't something which you can just "rename" as they are two different things.
Correct me if I'm wrong here but these API lists used to show game's required DX version while you expected that to indicate which D3D interface a game is using and they didn't match.
To fix that a more correct option would be to add D3D entry in addition to DX one instead of renaming the DX one to D3D.
Whether the DX entry even has any value is a different question though - to me it seems like it would be just duplicating the info from system requirements.
 
I wrote that I'm already aware that DirectX includes other APIs besides Direct3D, and that games can use them without using D3D, hence the OpenGL example.

Renaming was valid since the lists are and were always tracking Direct3D versions, not DirectX. They are directly linked to the "Direct3D" field on the games' pages.

The D3D lists are not supposed to include OpenGL games that use non-D3D APIs from DirectX.

I even proposed to create actual DirectX lists if they insisted on having them, but in the end it was determined to not be of much value.
 
Last edited:
Well suit yourself.

I went through a bunch of older games I've had lying around yesterday and changed their info according to what dgVoodoo2 (and apitrace in some cases) tracing is showing.
 
I think you're misunderstanding me. We are actually in agreement.

Your method is how it should be. How are you determining the exact shader model though? Is it reflected in the trace logs? I haven't had a chance to check yet.

You don't have to add .0 to D3D that don't also have a *.1 variant, or DDraw.
 
Last edited:
How are you determining the exact shader model though? Is it reflected in the trace logs? I haven't had a chance to check yet.
Tracing saves the shaders which are submitted into the API and these come with a header indicating their version. So it's basically just a search for shader versions in the trace logs - you can decipher the SM version from that easily.

Granted it's not a 100% bullet proof solution since I imagine that some games may in fact use different shaders for different levels and in such cases you should trace the API calls for each loading basically.

So it's possible that some games which use D3D9 but show only 1.1 or 2.0 shaders in the trace of first level loading would use 2.x or 3.0 shaders on some later level. But tracing the whole game isn't something I have time for =) or is even possible considering the performance implication of tracing in general - some games are literally unplayable with apitrace wrapper, like single digit fps.

It's also a problem for D3D12 titles since these don't seem to show shaders in tracing in a human readable form - likely because PSOs are compiled prior to being submitted for execution?
 
Damn, I thought I had it properly set up back when I did all those tests. So I had it wrong all along; spent days testing dozens of games without realizing it. *facepalm*

Apparently I did have it set up correctly, however for some reason, Debugview does not show the DX traces, only the dgvoodoo messages.

After you mentioned Debugview++, I tried it and they all show up.
 
That was because back then we didn't know a method to test which model a game uses.

With the tracing method, if you're confident the results are accurate, you can talk to them on their discord server to re-implement it.

Although, it's still not guaranteed since it might be deemed not important enough.
 
Their reasoning seem to be about this info being useless to the PCGW users - which I kinda agree with as it doesn't really help with anything.
But to be fair about 1/2 to 2/3 of info on PCGW pages are useless to me as a user so ¯\_(ツ)_/¯
 
@DmitryKo
While checking a game that seems to be D3D6, instead of these:

Code:
IDirect3DDevice3:DrawPrimitiveVB
IDirect3DDevice3::EnumZBufferFormats

I found these:

Code:
Direct3DDevice:DrawPrimitive
Direct3D::EnumZBufferFormats

Are they the same thing?

Also, whats the source for the interfaces table?

For Direct3D 2 and 3, I don't suppose they can be distinguished?

When checking a 2D game, does DirectDrawSurface (without a number), mean the game uses DDraw1?
 
Last edited:
There's this game, Zoo Tycoon. It's a 2D game, however it's making D3D7 calls, and would crash if d3dim700.dll isn't present. Why would a game like that require 3D related interfaces?

Here's the trace log:
 

Attachments

  • ZooTycoon.zip
    1.3 MB · Views: 2
Are they the same thing?
My knowledge here is limited and I'm as interested in what DmitryKo will say but D3D6 has all the previous D3D interfaces in it - meaning that a game may use them despite creating a D3D6 device. This is something I've mentioned above as I've ran into several such games myself.

When checking a 2D game, does DirectDrawSurface (without a number), mean the game uses DDraw1?
That's my understanding.
DirectDrawSurface2 would be DDraw2
DirectDrawSurface3 would be DDraw5
DirectDrawSurface4 is DDraw6
But I'm using the DX version with which these DDraw updates shipped to name the DDraw versions - which weren't ever public until MS reset all versioning with DX7 I think?

Why would a game like that require 3D related interfaces?
Maybe this is the way they check if the GPU is fast enough? =)
Can be many reasons from "we forgot to remove it" to actually using the 3D API for something.
 
It all started with trying to run older games under XP in VMware. I had noticed that only D3D9 is accelerated properly; D3D8 is mostly ok with some visual and performance issues, but D3D7 and older are most of the time broken.
So it's modern CPU and video card, running Windows XP guest on a bare-metal hypervior in VMWare Workstation? Or is it a hosted hypervisor that redirects guest OS kernel calls to the host OS kernel?

Unless you need to run 16-bit Windows software, why not just run the executables in Windows 10?


I thought perhaps a wrapper would help. dgvoodoo2 does not support XP, and there's no compatible D3D2-7 to 9 wrapper, however for D3D8 I could use d3d8to9.

I then looked at the Direct3D 8 games list on pcgamingwiki, and tried a few with d3d8to9, but they didn't work; no wrapping. That's when I started to check which D3D version a game actually uses and quickly noticed a LOT of the listed games weren't D3D8 at all. The same issue with older lists. Quite a few DDraw-only games are also wrongly listed as Direct3D.
Apparently I did have it set up correctly, however for some reason, Debugview does not show the DX traces, only the dgvoodoo messages.

After you mentioned Debugview++, I tried it and they all show up.

The hoops we jump through to watch some blurry pieces of ancient visual art :)


How are you determining the exact shader model though? Is it reflected in the trace logs?
The shader signature is listed in the trace log, however I can't see any purpose of documenting shader model versions for each game, it's not something that end users can control or should even care about.
 
Last edited:
Direct3DDevice3:EnumZBufferFormats
Direct3D::EnumZBufferFormats

Are they the same thing?
Huh! Didn't even notice that these numbers are missing in the trace logs.

This one above is indeed IDirect3D3::EnumZBufferFormats; it's corrected in my table now.

Direct3DDevice:DrawPrimitive

This should have been reported as IDirect3DDevice2:DrawPrimitive, i.e. Direct3D 5.0; there is also a different method from Direct3D 6.0, IDirect3DDevice3::DrawPrimitiveVB.

For Direct3D 2 and 3, I don't suppose they can be distinguished?

Of course all COM interfaces can be distiguished, they are defined using different IIDs (i.e. globally unique identifiers or GUID).

It's just how the author of dgVoodoo2 reports interface names for Direct3D 2.0-7.1 in his debug layer code; Direct3D 8.0 and 9.0 API trace logs do use correct numbers (but don't expand IID names from GUIDs). All of them are missing the leading capital "i". :)


The universally accepted C++ notation would be for example IDirect3DDevice9::SetRenderState, where IDirect3DDevice9 is a COM "interface" ("class" in C++) and SetRenderState is a "method" from that interface ("class member function" in C++).

:: notation (C++ "scope resolution operator") helps you dustinguish between similarily named methods from different interfaces, i.e. IDirect3DDevice7::SetRenderState and IDirect3DDevice2::SetRenderState.

(FYI, Direct3D is designed around using references to COM interfaces and IIDs, as well as C-style structs, enums, and #define/macros - so you won't really encounter :: notation in code samples, and there would be mostly pointer dereferencing -> instead.
This is to facilitate backward compatibility with C-style coding, as C doesn't know anything about classes and member functions, but understands function type definitions and calling functions by pointers.)


Also, whats the source for the interfaces table?
D3D.h and DDRAW.h from the current Windows SDK. You can find copies on GitHub, for example

https://github.com/apitrace/dxsdk/blob/master/Include/d3d.h
https://github.com/apitrace/dxsdk/blob/master/Include/ddraw.h

I've only listed names unique for each Direct3D release, so you could just search for these names; make sure to also check the IIDs in QueryInterface calls though.

When checking a 2D game, does DirectDrawSurface (without a number), mean the game uses DDraw1?
Well, Microsoft starts their numbering system from zero, i.e. an empty space, so it should have been a sequence of IDirectDraw, IDirectDraw1, IDirectDraw2, IDirectDraw3,IDirectDraw4 etc. - except that 1 and 3 were lost in the process (3 was probably designed for the ActiveMovie control (Open Control eXtension) for IE 3.0, later refactored into DirectShow), so there are only IDirectDraw and IDirectDraw2 in the DirectX SDK 2.0-5.0.

I'm not sure when these two interfaces were actually released, most likely both of them were from the DirectX SDK 2.0, but the latter could be added in the DIrectX SDK 3.0 a few months later. It's hard to tell now, since all ancient SDK releases have been removed from Microsoft Downloads, and DDRAW.h definitions are not versioned with conditional compilation directives (unlike D3D.h which wraps type definitions with #if (DIRECT3D_VERSION == 0x...) ... #endif blocks).

Make anything you want out of this information, I don't think Microsoft ever advertised numbered releases of DirectDraw to the public...

D3D6 has all the previous D3D interfaces in it - meaning that a game may use them despite creating a D3D6 device
Yes, you can use any of these interfaces once you've created the Direct3D device - though for example mixing ExecuteBuffer with DrawPrimitive would be a terrible idea for your performance.

The way they were designed, each interface has a full set of methods to provide a complete implementation of the rendering pipeline. So you could just use IDirect3DDevice for ExecuteBuffer based implementation to support software rendering or the most basic hardware accelerators like S3 Virge, IDirect3DDevice2 for DrawPrimitive and SetRenderTarget methods to support cards with hardware triangle setup and additional front/back buffer formats, and IDirect3DDevice3 for VertexBuffer and SetTextureStageState to support cards with vertex buffers and multitexturing; the rest of the methods were mostly copying functionality from the earlier implementations.

I'm using the DX version with which these DDraw updates shipped to name the DDraw versions - which weren't ever public until MS reset all versioning with DX7 I think?
Yep, they never boased DirectDraw version numbers, maybe except for the final release of DirectDraw 7 which accompanied the refactored Direct3D 7.0 with hardware TnL (transform and lighting) for NVidia GeForce 256.

There's this game, Zoo Tycoon. It's a 2D game, however it's making D3D7 calls, and would crash if d3dim700.dll isn't present. Why would a game like that require 3D related interfaces?
Can be many reasons from "we forgot to remove it" to actually using the 3D API for something.
I've checked the trace logs, and this game only creates Direct3D 7 interface, queries it for some unknown IID with two dozen failures, and closes the interface, repeats these steps for a second time, then sets the render target surface, creates a software emulation device, and tests it for supported render states and texture operations. Then does nothing with the Direct3D device during the next few thousand DirectDraw calls. Finally, closes the Direct3D device and resets texture stages, then exits.

So it looks like a side effect of including some middleware or helper library, which only did an initialization and a feature query. It would probably include the option to use Direct3D for hardware alpha blending and/or bilinear filtering. The unknown IID in question might be related to DirectShow video renderer though.


That being said many older games do just that it seems - query some DD 5.0 and then proceed to use functions from DD 1.0 only ¯\_(ツ)_/¯

Do you have an example trace? This could also be a side effect of using some 3rd party middleware...
 
Last edited:
So it's modern CPU and video card, running Windows XP guest on a bare-metal hypervior in VMWare Workstation? Or is it a hosted hypervisor that redirects guest OS kernel calls to the host OS kernel?

I'm not well versed in virtualization, but I guess it's the second option. I'm running Windows 10 on the host PC. I then installed VMware Workstation, and then created a VM and installed XP.

Unless you need to run 16-bit Windows software, why not just run the executables in Windows 10?

I was mostly experimenting to see how viable it is. Some games have issues on Windows 10 that cannot be remedied with dgvoodoo2, like failing to launch or crashing.

I'm not sure when these two interfaces were actually released, most likely both of them were from the DirectX SDK 2.0, but the latter could be added in the DIrectX SDK 3.0 a few months later. It's hard to tell now, since all ancient SDK releases have been removed from Microsoft Downloads, and DDRAW.h definitions are not versioned with conditional compilation directives (unlike D3D.h which wraps type definitions with #if (DIRECT3D_VERSION == 0x...) ... #endif blocks).

DirectX 1.0 SDK can be found on archive.org: https://archive.org/details/gamesdk

This is the content of ddraw.h: https://pastebin.com/5suKjYne

DirectX 2.0 SDK: https://archive.org/details/directx2sdk

I've checked the trace logs, and this game only creates Direct3D 7 interface, queries it for some unknown IID with two dozen failures, and closes the interface, repeats these steps for a second time, then sets the render target surface, creates a software emulation device, and tests it for supported render states and texture operations. Then does nothing with the Direct3D device during the next few thousand DirectDraw calls. Finally, closes the Direct3D device and resets texture stages, then exits.

So it looks like a side effect of including some middleware or helper library, which only did an initialization and a feature query. It would probably include the option to use Direct3D for hardware alpha blending and/or bilinear filtering. The unknown IID in question might be related to DirectShow video renderer though.

Let's put it this way; if I edit the game's page on pcgamingwiki, should I list it as using Direct3D? Based on your analysis of the traces, I suppose the answer is no?
 
Last edited:
Back
Top