New Release D3D9Client Development

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,336
Reaction score
378
Points
83
Website
users.kymp.net
I mean: The Visual-Studio-Projects 'till now assumed the environment variable DXSDK_DIR to be set to the correct location on a build machine.
I tried to pass the $(DXSDK_DIR) environment variable to include libraries but the CMake got confused about it. So, I went the easy way-a-round by using set(DXSDK_DIR "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)") to move forward with my first attempt to use the CMake. Didn't want to get stuck on that too long.

This would look nice and simple if it works:
Makefile:
set(DXSDK_DIR extractFromEnvironmentOrDefault("%DXSDK_DIR%"  "C:/Program Files (x86)/Microsoft DirectX SDK (June 2010)"))
 

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
8,990
Reaction score
1,077
Points
203
Location
VA
Website
alteaaerospace.com
I have the x64 D3D9 client built and linked successfully now, but I'm having trouble running it from my x64 Orbiter install. I activated the module successfully, but it fails during load with this:

missing_dx_runtimes_Screenshot 2021-08-09 122411.png

I think it needs the 64-bit DX9 runtimes? I installed the runtimes from https://www.microsoft.com/en-us/download/confirmation.aspx?id=8109 listed in the D3D9 PDF, but I suspect those are just 32-bit. Is there a 64-bit package of the D3D9 runtimes I need to install?


EDIT:
My x64 orbiter.log shows this:
Code:
**** Orbiter.log
000000.000: Build Aug  9 2021 [v.210809]
000000.000: Timer precision: 1e-07 sec
000000.000: Found 0 joystick(s)
000000.000: Module AtlantisConfig.dll .... [Build 210809, API 210809]
000000.000: Module AtmConfig.dll ......... [Build 210809, API 210809]
000000.000: Module DGConfigurator.dll .... [Build 210809, API 210809]
000000.000: ---------------------------------------------------------------
000000.000: BaseDir    : D:\GitHub\orbiter\out\build\x64-Debug\
000000.000: ConfigDir  : D:\GitHub\orbiter\out\build\x64-Debug\Config\
000000.000: MeshDir    : D:\GitHub\orbiter\out\build\x64-Debug\Meshes\
000000.000: TextureDir : D:\GitHub\orbiter\out\build\x64-Debug\Textures\
000000.000: HightexDir : D:\GitHub\orbiter\out\build\x64-Debug\Textures2\ [[DIR NOT FOUND!]]
000000.000: ScenarioDir: D:\GitHub\orbiter\out\build\x64-Debug\Scenarios\
000000.000: ---------------------------------------------------------------
000000.000: D3D9 DLLs  : C:\WINDOWS\SYSTEM32\d3d9.dll [v 10.0.19041.928]
000000.000: ---------------------------------------------------------------
000000.000: Module D3D9Client.dll ........ [Build 210809, API 210809]
000000.000: Module XRSound.dll ........... [Build 210809, API 210809]
000000.000:
000000.000: **** Creating simulation session
000000.000: D3D9: [DirectX 9 Initialized]
000000.000: D3D9: [3DDevice Initialized]
 
Last edited:

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,336
Reaction score
378
Points
83
Website
users.kymp.net
I have the x64 D3D9 client built and linked successfully now, but I'm having trouble running it from my x64 Orbiter install. I activated the module successfully, but it fails during load with this:

I think it needs the 64-bit DX9 runtimes? I installed the runtimes from https://www.microsoft.com/en-us/download/confirmation.aspx?id=8109 listed in the D3D9 PDF, but I suspect those are just 32-bit. Is there a 64-bit package of the D3D9 runtimes I need to install?

But you were able to run the x64 binary package (release and debug) I posted a week ago, right ? Maybe you are trying to link it to some other version ?
You could check the dependencies and see if you have the necessary files in /System32/ and just in case /SysWOW64/

I am no expert in building x64 but why do all paths lead to /System32/ and not in /SysWOW64/ there are plenty of d3d9 related DLL's there ?

Also any ideas why the forum scales down attached images ? They become next to unreadable and the file size increases. (Original size 24 kb now it's over 10x bigger)
 

Attachments

  • depends.png
    depends.png
    357.9 KB · Views: 6

DaveS

Space Shuttle Ultra Project co-developer
Addon Developer
Donator
Beta Tester
Joined
Feb 4, 2008
Messages
9,133
Reaction score
398
Points
173
I am no expert in building x64 but why do all paths lead to /System32/ and not in /SysWOW64/ there are plenty of d3d9 related DLL's there ?
I'm no Windows expert but from what I can gather, SysWOW64 is where Windows x64 stores all of its x86 system files, so it analogous to C:\Program Files (x68) that 32-bit programs default to C:\Program Files (x68) while 64-bit programs go into C:\Program Files.
 

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
1,775
Reaction score
277
Points
83
WOW64 means [W]indows [O]n [W]indows-[64], so in that folder the 32bit world lives - logical, right?

Back to the "missing runtimes": I don't remember having installed special x64 DirectX runtimes. I guess the installer was aware of being run on a 64-bit system and did the right thing.
The check at D3D9Client startup might not be 100% accurate, though - It was developed when there was ONLY a 32bit Orbiter!
I'll take a look at that code section.
 

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
8,990
Reaction score
1,077
Points
203
Location
VA
Website
alteaaerospace.com
But you were able to run the x64 binary package (release and debug) I posted a week ago, right ? Maybe you are trying to link it to some other version ?
You could check the dependencies and see if you have the necessary files in /System32/ and just in case /SysWOW64/

Yes, both the Release and Debug binary packages run fine for me. I checked the Orbiter.log from that instance, and the DLLs that work are:

Code:
    000000.000: D3D9 DLLs  : C:\WINDOWS\SYSTEM32\d3d9.dll [v 10.0.19041.928]
    000000.000:            : C:\WINDOWS\SYSTEM32\d3dx9_43.dll [v 9.29.952.3111]

In the version that I built, though, Orbiter.log only shows the first DLL:

Code:
000000.000: D3D9 DLLs  : C:\WINDOWS\SYSTEM32\d3d9.dll [v 10.0.19041.928]

It could be due to me manually installing the D3D9 client files -- most of the files (except for the newly built DLL, of course) I took from the 32-bit D3D9 zip package. I will dig into that more tonight.

EDIT:
I got it to work like this:
  1. Extract the OrbiterX64-dbg-bin_with_D3D9.zip binary package from Jarmonik into my orbiter\out\build\x64-Debug folder.
  2. Copy my newly built x64 D3D9Client.dll into orbiter\out\build\x64-Debug\Modules\Plugin, overwriting the DLL that was there.
  3. Rebuild the Orbiter x64 target in VS 2019.

So the root issue was probably some D3D9 config files that I manually copied over incorrectly the first time.
 
Last edited:

kuddel

Donator
Donator
Joined
Apr 1, 2008
Messages
1,775
Reaction score
277
Points
83
@dbeachy1 , just for clarification :
The DLLs listed in this pat of Orbiter.log
Code:
000000.000: ---------------------------------------------------------------
000000.000: D3D9 DLLs  : C:\WINDOWS\SYSTEM32\d3d9.dll [v 10.0.19041.928]
000000.000:            : C:\WINDOWS\SYSTEM32\d3dx9_43.dll [v 9.29.952.3111]
000000.000: ---------------------------------------------------------------
are System DLLs, so they are not part of D3D9Client!
These are the runtime DLLs which should have been installed by DirectX End-User Runtimes (June 2010) (<= Note, this is a link) installer.

....and I've checked the code that reports this: It's bit-width-agnostic.
 

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,410
Reaction score
297
Points
83
Website
orbit.medphys.ucl.ac.uk
Still no luck compiling D3D9Client, and getting more confused ....
Is there a readme that explains the steps to compile, including prerequisites that need to be installed?

I installed the DirectX End-User Runtimes (June 2010) package. Do I also need to install any NVidia SDK stuff?
Should this compile with CMake, using the provided CMakeLists.txt, or do I have to use the VS solution files directly?
When compiling with CMake, the CMAKE_BINARY_DIR has to point to an Orbiter installation, correct?
When compiling directly from the VS solution directory, does the D3D9Client git repository have to be placed directly inside an Orbiter installation?
I found VS solution files in Orbitersdk/D3D9Client, but the VS2019 version only seems to be set up for x86. Should I use the VS2015 version and convert to VS2019?
I got errors relating to _wassert, had to convert all instances to assert. Has this been seen before?

Sorry for all the questions. I'm new to compiling the D3D9client, so a beginner's guide would help me a lot.
 

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,336
Reaction score
378
Points
83
Website
users.kymp.net
Still no luck compiling D3D9Client, and getting more confused ....
Is there a readme that explains the steps to compile, including prerequisites that need to be installed?
I installed the DirectX End-User Runtimes (June 2010) package. Do I also need to install any NVidia SDK stuff?
Sadly, we don't have any readme yet. There's been lot of new things to learn and I haven't found the time to write that. Also some things regarding the build process are still under development.
The End-User Runtimes are not sufficient to actually build the client you would need at-least: DirectX SDK (June 2010)
That's the latest SDK that's available as separate download. The newer DirectX SDKs are bundled with Windows 10 SDK and I haven't tried those yet. No nVidia SDK required as far as I know. If you are missing a proper SDK then there's gonna be lot of compilation errors.

Should this compile with CMake, using the provided CMakeLists.txt, or do I have to use the VS solution files directly?
I haven't tried the "Ninja" yet, so, I don't know how that works yet. I have used the CMake-GUI to create VS Solution and Project files and after that I have clicked the D3D9Client.sln to launch the VS and build the projects from there. Usually I have removed BUILD_ALL, INSTALL "Projects" from the Solution.

When compiling with CMake, the CMAKE_BINARY_DIR has to point to an Orbiter installation, correct?
Yes, that is correct, the same that is used to build the Orbiter. And the CMAKE_SOURCE_DIR must point to the local D3D9Client.git repository.

When compiling directly from the VS solution directory, does the D3D9Client git repository have to be placed directly inside an Orbiter installation?
No, I have no idea what happens if someone tries that. CMake should copy all necessary files to CMAKE_BINARY_DIR. Also CMake should copy/update the Shaders during every build.

I found VS solution files in Orbitersdk/D3D9Client, but the VS2019 version only seems to be set up for x86. Should I use the VS2015 version and convert to VS2019?
I got errors relating to _wassert, had to convert all instances to assert. Has this been seen before?
I have left the old project files in-place just in case if we need them. There's been no reports regarding "_wassert" and it's been there probably 2-3 years. I have no idea why it fails.

CMake is configured to place the modules directly in /Modules/Plugin/ they do not go to "/debug/" "/release/" sub-folders.
And the Shaders (*.fx and *.hlsl) must be in /Modules/D3D9Client/
 
Last edited:

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,410
Reaction score
297
Points
83
Website
orbit.medphys.ucl.ac.uk
I finally managed to compile D3D9Client x64 and run it under Orbiter x64! Thanks for your help in getting my problems worked out.

FYI, It worked straight away for me when doing a debug build, but to get it to work in a release build, I had to fix problems with _wassert and assert, by adding the following in D3D9Client.h after #include <assert.h>:
Code:
#if defined(NDEBUG)
#define _wassert(message,filename,line)
#endif

#undef assert
#define assert(x) (x)
"_wassert" was undefined for me in the Release build (which is apparently expected according to this: "The signature of the _assert function isn't available in a header file. The signature of the _wassert function is only available when the NDEBUG macro isn't defined.")

Even more worrying, "assert" was defined as
Code:
#ifdef NDEBUG

    #define assert(expression) ((void)0)

#else
  ...
in assert.h. In other words, the argument of assert wasn't even computed, leading to crashes.

I wonder if this is a change in behaviour between VS 2015 and VS 2019. Just to give you a heads-up of potential problems.
 

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,336
Reaction score
378
Points
83
Website
users.kymp.net
I finally managed to compile D3D9Client x64 and run it under Orbiter x64! Thanks for your help in getting my problems worked out.
It's great hear that it finally worked. I googled about the NDEBUG (i.e. NO DEBUG) flag and it would seem to work as intended. It's purpose seem to be disabling these debug assertions. I have never used NDEBUG flag and it looks like CMake would define it for Release builds. I wonder are there any alternatives for asserts we could use. Or should we try to undefine NDEBUG and let the asserts to work ?

How are the things with the rest of the Orbiter regarding assert behavior ?
 

GLS

Well-known member
Orbiter Contributor
Addon Developer
Joined
Mar 22, 2008
Messages
4,539
Reaction score
751
Points
138
According to Billy: The _assert and _wassert functions are internal CRT functions. They help minimize the code required in your object files to support assertions. We don't recommend that you call these functions directly.

Never had problems with assert(): it's there in debug builds to catch programmer errors (hard-coded stuff and not, e.g., file parse errors), and in release builds all that "instrumentation" disappears.
 

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,410
Reaction score
297
Points
83
Website
orbit.medphys.ucl.ac.uk
How are the things with the rest of the Orbiter regarding assert behavior ?
I have defined my own macros (in Src/Orbiter/Log.h: ASSERT and dASSERT). Log.h isn't currently exported to the SDK, so probably not visible to external plugin code. If it looks useful, I could copy it to Orbitersdk/include.
 

martins

Orbiter Founder
Orbiter Founder
Joined
Mar 31, 2008
Messages
2,410
Reaction score
297
Points
83
Website
orbit.medphys.ucl.ac.uk
Never had problems with assert(): it's there in debug builds to catch programmer errors (hard-coded stuff and not, e.g., file parse errors), and in release builds all that "instrumentation" disappears.
That is fine as long as you are not relying on the side effect of the argument of assert() being evaluated even if the assertion is not tested. So you can do

res = someFunction()
assert(SUCCEEDED(res))

but not

assert(SUCCEEDED(someFunction()))

if you rely on someFunction() being called.
 

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
8,990
Reaction score
1,077
Points
203
Location
VA
Website
alteaaerospace.com
For what it's worth, in my experience and from what I've read, the contents of the assert macros should never contain code that needs to run in production. i.e., the assert documentation says this:

This macro is disabled if, at the moment of including <assert.h>, a macro with the name NDEBUG has already been defined. This allows for a coder to include as many assert calls as needed in a source code while debugging the program and then disable all of them for the production version by simply including a line like:

#define NDEBUG

at the beginning of the code, before the inclusion of <assert.h>.

Therefore, this macro is designed to capture programming errors, not user or run-time errors, since it is generally disabled after a program exits its debugging phase.

The contents of the (uppercase) ASSERT macros in Visual Studio are only ever compiled into debug builds, not release builds, so it's probably safer to just use the uppercase ASSERT macros to prevent any unexpected side effects of having business logic inside a (lowercase) assert , which may or may not run in production builds (and having any assert macros run in production builds is counter-intuitive, at least to me). But that's just my perspective, which may or may not be "correct". :)
 

jarmonik

Well-known member
Orbiter Contributor
Addon Developer
Beta Tester
Joined
Mar 28, 2008
Messages
2,336
Reaction score
378
Points
83
Website
users.kymp.net
Therefore, this macro is designed to capture programming errors, not user or run-time errors, since it is generally disabled after a program exits its debugging phase.

We have used the assert to capture user and run-time errors as well. I thought it's better to assert when something goes very wrong rather than CTD in some point later on. So, is there a better way to capture run-time errors in release builds (hopefully equally easy) ?
 

GLS

Well-known member
Orbiter Contributor
Addon Developer
Joined
Mar 22, 2008
Messages
4,539
Reaction score
751
Points
138
We have used the assert to capture user and run-time errors as well. I thought it's better to assert when something goes very wrong rather than CTD in some point later on. So, is there a better way to capture run-time errors in release builds (hopefully equally easy) ?
For runtime errors you can throw an exception, catch it somewhere upstream, log the error and exit.
 

dbeachy1

O-F Administrator
Administrator
Orbiter Contributor
Addon Developer
Donator
Beta Tester
Joined
Jan 14, 2008
Messages
8,990
Reaction score
1,077
Points
203
Location
VA
Website
alteaaerospace.com
For runtime errors you can throw an exception, catch it somewhere upstream, log the error and exit.

FWIW, I agree -- it's a lot easier for end users to post a log file than try to copy down the cryptic stuff that pops up on an assert's dialog box, IMO.

Another similar approach is to define your own macro (maybe named "PRODUCTION_ASSERT(...)"?) that invokes your own custom, static function that writes to the log file an exits if the supplied expression evaluates to false or null. But I still wouldn't want to put the actual business logic call inside the macro -- I would just save the result of the business logic call to a variable and then pass that variable to the PRODUCTION_ASSERT. For example, doing this:

Code:
const int myResult = DoSomethingCool(...);
PRODUCTION_ASSERT((myResult > 0), "DoSomethingCool returned a bad value!");

...seems much more intuitive (and safer) to me than doing this:

Code:
PRODUCTION_ASSERT((DoSomethingCool(...) > 0), "DoSomethingCool returned a bad value!");

That's just my perspective, though. Every developer has their own preferred style. :)
 
Top