-
Notifications
You must be signed in to change notification settings - Fork 92
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can't wrap custom d3d8.dll with d3d8to9 #134
Comments
You should also open another issue about that lighting bug, since it's kinda within the aims of dxwrapper to fix too. |
I wasn't sure if I was supposed to do this since it's a very specific issue. But I'll do it, thanks for letting me know. |
I decided to run the debug version of DxWrapper to see if that would show useful logs. With the same config as before and
The custom d3d8.dll loads correctly and works fine in-game here. Now with |
I am able to replicate this behavior on my system. It seems setting "D3d8to9" to true prevents the running of whatever DLL is specified in "RealDLLPath". Attached is two screenshots from ProcExp showing the result of flipping "D3d8to9" between true/false. I am a novice when it comes to C++ but I am trying my best to look through the code to see why this is. My guess is maybe the logic/issue involves lines 187 and 435 of Dllmain.cpp. My two theories:
|
This is nothing to do with the C++ code. If you convert the game to use d3d9 (using d3d8to9) then it does no good to load a 3rd party d3d8.dll since the game is using d3d9 not d3d8. Think about it this way, all 3rd party wrappers are hard coded to load the System32 dll files. So a 3rd party d3d8.dll wrapper will load System32 d3d8.dll. It looks like this:
However, when using 'd3d8to9' dxwrapper will load d3d9.dll rather than d3d8.dll like this:
If dxwrapper tries to load a 3rd party dll before loading d3d9.dll then there will be no way for the game to use d3d9. See below:
There are two ways around this. The first way around this would be to hook the System32 d3d8.dll functions so that when the game calls them it will go back to dxwrapper, like this:
The other solution is to modify the 3rd party wrapper to have it load dxwrapper rather than the System32 d3d8.dll, like this:
All this to say that it is a lot more work to support loading a 3rd party d3d8.dll and d3d8to9 at the same time. I have done a few custom developments of this (see here and here for examples). In both of these cases I chose to modify the 3rd party dll since that was the easier solution. I have thought about making a feature in dxwrapper to support this but I probably won't get around to it anytime soon. Note: if you just want the dll to be loaded you can use either the 'LoadCustomDllPath' or the 'LoadPlugins' feature of dxwrapper. |
Thank you for the response and explanation @elishacloud, I appreciate it. In this specific use case the "3rd-party" dll is just an older version of Microsoft's d3d8.dll from Windows 10 19H1. Post 20H1 Microsoft seems to have replaced the d3d8.dll found in the System32 dir with d3d8thk.dll. This new version seems to carry some regressions in terms of lighting and shadows, specifically for the game Freelancer, which I guess folks will have to live with for now. |
If you are using Microsoft's d3d8.dll then enabling Does Can you give more details on the lighting issue? Maybe this is something we can fix in |
Not sure, I am running it in a VM just so I can grab the DLLs. Maybe @BC46 can answer since they originally found the older DLL trick.
I just tried this, I can see that dxwrapper is loading the older d3d9.dll but I am still seeing the lighting / shading issue.
Sure, I have attached a zip with two comparison screenshots (and also my dxwrapper log during the older d3d9.dll test). But here is a description of what we are seeing if you do not want to download the zip. Issue: In specific interior locations lighting, shading, and transparency is broken with d3d9.dll
Side Note: |
It would be good to know if d3d8to9 had an issue on the older Windows 10 with this game. I think the solution may be to fix d3d8to9 so that it does not have this lighting issue. In fact, does the lighting issue happen when using d3d8to9 on older OS's, like Windows 7, with this game? BTW: I'm not sure, but I think maybe the change that Microsoft did after Windows 10 19H1 was to redirect Direct3D8 to go to the Driect3D9 drivers. |
I have a PC running Windows 10 19H1 which I use for compatibility testing. I played Freelancer (the game in question) using just d3d9to9 on it and it ran completely fine without the lighting bug. Windows 10 version 2004 (20H1), or build 19041 is the first known Windows version where the lighting bug appears. People started reporting this issue shortly after the release date of this build. Players who still use Windows 7 & 8 to play this game can confirm that they've never encountered the issue before. However, these older Windows releases, including Vista and even newer XP service packs do all have a Freelancer DirectX compatibility issue regarding glass reflections on the ship windows. However, it's so minor that it's hardly worth mentioning. As far as I know, dgVoodoo is the only graphics wrapper that fixes both the lighting bug and the glass reflections issue properly on modern Windows versions.
I currently don't have access to a PC/VM running such older versions of Windows. Though I think it's unlikely that d3d8to9 could be the culprit since the lighting bug seems to show depending on the Windows version/build, regardless of whether d3d8to9 is used.
All I know myself is that the DirectX rendering pipeline has been heavily modified since the release of Windows 10 2004, which I'm assuming is the cause of the lighting bug. |
Ok, it sounds like d3d8to9 is not causing the issue. Have you tried using d3d8to9 and then using Direct3D9 to Vulkan? This way you can bypass whatever the Windows bug is. |
Yes, I tried that a while ago. I tested Freelancer using d3d8to9 + DXVK's |
I see. Maybe I should fix the lighting issue in my d3d9 wrapper? The way I have coded the d3d8to9 function is that it goes through the d3d9 wrapper. So any d3d9 fixes I add will also fix d3d8to9. |
If you think it's worth the effort, then that would be amazing. I'll provide any additional info and help if needed. |
I wanted to do some more research and @elishacloud's info regarding Direct3D8 being redirected to the Direct3D9 drivers after Windows update 19H1 gave me some clues as to where I could look. First I should mention how Freelancer makes use of DirectX 8's lights. Basically the game uses so-called Thorn scripts to specify what kind of lights should be used in a scene. Inherently these are just compressed Lua scripts. Here's an example of how a light is set in one of the scripts that has been decompressed: {
entity_name = "ambi_LtG03_Basement_Ohd_Ylw",
type = LIGHT,
template_name = "",
lt_grp = 3, srt_grp = 0, usr_flg = 0,
spatialprops =
{
pos = { -5.010058, 0, 1.758013 },
orient = { { -0.105263, -0.008535, -0.994408 },
{ 0.977260, 0.184208, -0.105029 },
{ 0.184075, -0.982850, -0.011049 } }
},
lightprops =
{
on = Y,
color = { 234, 192, 115 },
diffuse = { 0.623529, 0.576471, 0.376471 },
specular = { 0, 0, 0 },
ambient = { 0.086275, 0.086275, 0.07451 },
direction = { 0, 0, 1 },
range = 100,
cutoff = 179,
type = L_SPOT,
theta = 179,
atten = { 1, 0, 0 }
}
} If you look closely at the parameters in the A while ago I talked to another Freelancer modder about the lighting bug. After a small investigation they concluded the light type I really wanted to look for a better solution, and based on the clue regarding the redirection of Direct3D8 to the Direct3D9 drivers, I checked out the documentation for the lights from both DirectX 8 and DirectX 9. One thing that stood out to me right away was that the description for the members I wanted to find out whether or not the sudden support of the three values in DirectX 9 is the cause of the lighting bug. Though I did not know what the given light values for After some trial and error, I came up with this: HRESULT m_IDirect3DDevice8::SetLight(DWORD Index, CONST D3DLIGHT8 *pLight)
{
D3DLIGHT8* pLightEdit = const_cast<D3DLIGHT8*>(pLight);
// Only the light type D3DLIGHT_SPOT suffers from the lighting bug
if (pLightEdit->Type == D3DLIGHTTYPE::D3DLIGHT_SPOT)
{
// Fix lighting bug
pLightEdit->Falloff *= 0.5f;
pLightEdit->Theta *= 0.5f;
// Impose minimum Falloff to ensure shadows won't look too sharp
if (pLightEdit->Falloff < 0.6f)
pLightEdit->Falloff = 0.6f;
}
return ProxyInterface->SetLight(Index, pLightEdit);
} Using the d3d8 wrapper with this code in Freelancer completely rectifies the lighting bug. Basically I reduced the I should mention that I can't confirm whether my suspicion about |
If you have a possible regression range, bisecting with vmware workstation should really be a cakewalk. p.s. for all their bluntness, I think the DXVK people would appreciate you opening a ticket for whatever bug they have (though first I'd hope you tried all the d3d9 compatibility options in |
@BC46, thanks for your good research on this! I don't have the game so it is hard for me to test it. But I would like to make a generic fix for this.
The documentation that you showed is for Windows CE, it may not be applicable to Windows XP or even Windows 7. Windows CE may be using a cut-down version of DirectX. Also, one thing I have seen in the past is that the DirectX APIs were more forgiving back then. Now Microsoft keeps adding more checks and rejecting API calls that used to work. If we look at the documentation here we can see that What if you change the code to look more like this?: HRESULT m_IDirect3DDevice8::SetLight(DWORD Index, CONST D3DLIGHT8* pLight)
{
D3DLIGHT8* pLightEdit = const_cast<D3DLIGHT8*>(pLight);
// Fix 'Phi'
if (pLightEdit->Phi < 0.0f)
{
pLightEdit->Phi = 0.0f;
}
if (pLightEdit->Phi > M_PI)
{
pLightEdit->Phi = M_PI;
}
// Fix 'Theta'
if (pLightEdit->Theta < 0.0f)
{
pLightEdit->Theta = 0.0f;
}
if (pLightEdit->Theta > pLightEdit->Phi)
{
pLightEdit->Theta = pLightEdit->Phi;
}
return ProxyInterface->SetLight(Index, pLightEdit);
} |
One more thing you could try is since the documentation claims that You could also try this one: HRESULT m_IDirect3DDevice8::SetLight(DWORD Index, CONST D3DLIGHT8* pLight)
{
D3DLIGHT8* pLightEdit = const_cast<D3DLIGHT8*>(pLight);
pLightEdit->Falloff = 0.0f;
pLightEdit->Phi = 0.0f;
pLightEdit->Theta = 0.0f;
return ProxyInterface->SetLight(Index, pLightEdit);
} Edit: this might be the best idea since the code I see on the Internet for d3d8 don't seem to ever set any of these three values and they tend to zero the memory before using: D3DLIGHT8 light;
ZeroMemory( &light, sizeof(D3DLIGHT8) ); |
Here is some good documentation on how this works in DirectX: http://www.directxtutorial.com/Lesson.aspx?lessonid=9-4-9 |
I think this worked because I believe this is generic code that should fix this in all cases: #define _USE_MATH_DEFINES
#include <math.h>
HRESULT m_IDirect3DDevice8::SetLight(DWORD Index, CONST D3DLIGHT8* pLight)
{
if (!pLight)
{
return D3DERR_INVALIDCALL;
}
D3DLIGHT8 LightEdit;
memcpy_s(&LightEdit, sizeof(LightEdit), pLight, sizeof(LightEdit));
// The maximum allowable value for 'range' is the square root of FLT_MAX.
static float MaxRange = sqrtf(FLT_MAX);
if (LightEdit.Range > MaxRange)
{
LightEdit.Range = MaxRange;
}
switch (LightEdit.Type)
{
case D3DLIGHTTYPE::D3DLIGHT_SPOT:
// 'Phi' must be between 0 and pi.
if (LightEdit.Phi < 0.0f)
{
LightEdit.Phi = 0.0f;
}
if (LightEdit.Phi > M_PI)
{
LightEdit.Phi = M_PI;
}
// 'Theta' must be in the range from 0 through the value specified by 'Phi'.
if (LightEdit.Theta < 0.0f)
{
LightEdit.Theta = 0.0f;
}
if (LightEdit.Theta > LightEdit.Phi)
{
LightEdit.Theta = LightEdit.Phi;
}
// 'Falloff' a falloff other than 1.0 takes time to process, developers usually use 1.0
LightEdit.Falloff = 1.0f;
break;
case D3DLIGHTTYPE::D3DLIGHT_DIRECTIONAL:
LightEdit.Range = 0.0f; // This member does not affect directional lights.
__fallthrough;
case D3DLIGHTTYPE::D3DLIGHT_POINT:
LightEdit.Falloff = 0.0f;
LightEdit.Phi = 0.0f;
LightEdit.Theta = 0.0f;
break;
default:
return D3DERR_INVALIDCALL;
}
return ProxyInterface->SetLight(Index, &LightEdit);
} Please let me know if this works. |
Putting aside that this should all be easily readable in the offline docs shipped with the sdk, you are right that the windows CE version was different. |
Thank you for the links and the code snippets @elishacloud! With the first and third snippet the lighting bug was still present in the game unfortunately; same result as this: The second one made all the objects either black or very dark: Would it be helpful if I sent a collection of |
Yes, this would be helpful. Thanks! |
I hope the logging format is a bit clear: d3dlight8_log.txt. |
Thanks for the logs! It seems like in almost every case (except index 4) it sets FallOff is always set to 1, which is the normal value, so we should not need to change that at all. I think what might be happening is that older versions of DirectX used to treat it differently when We can try something like this: HRESULT m_IDirect3DDevice8::SetLight(DWORD Index, CONST D3DLIGHT8* pLight)
{
if (!pLight)
{
return D3DERR_INVALIDCALL;
}
D3DLIGHT8 LightEdit;
memcpy_s(&LightEdit, sizeof(LightEdit), pLight, sizeof(LightEdit));
if (LightEdit.Type == D3DLIGHTTYPE::D3DLIGHT_SPOT)
{
if (LightEdit.Phi == LightEdit.Theta)
{
LightEdit.Theta = 0.0f;
}
}
return ProxyInterface->SetLight(Index, &LightEdit);
} Another idea is that after looking at the LUA: {
entity_name = "ambi_LtG03_Basement_Ohd_Ylw",
type = LIGHT,
template_name = "",
lt_grp = 3, srt_grp = 0, usr_flg = 0,
spatialprops =
{
pos = { -5.010058, 0, 1.758013 },
orient = { { -0.105263, -0.008535, -0.994408 },
{ 0.977260, 0.184208, -0.105029 },
{ 0.184075, -0.982850, -0.011049 } }
},
lightprops =
{
on = Y,
color = { 234, 192, 115 },
diffuse = { 0.623529, 0.576471, 0.376471 },
specular = { 0, 0, 0 },
ambient = { 0.086275, 0.086275, 0.07451 },
direction = { 0, 0, 1 },
range = 100,
cutoff = 179,
type = L_SPOT,
theta = 179,
atten = { 1, 0, 0 }
}
} I noticed that "cutoff" and "theta" are the same value. I guess that one of them affects |
Yes, that one did the trick. Thanks a lot! Slightly dimmer than what it looks like with the legacy d3d8.dll, but overall still a great result! As for the Lua script, setting |
Thanks for testing this! To solve the issue where the lighting is darker than the legacy d3d8.dll, I suspect you could just double the FallOff. However, I want to try and isolate the issue with the legacy d3d8.dll as much as possible to ensure we can match the functionality. If you would be willing to try some tests with the legacy d3d8.dll I would be grateful. I want to see if this only happens when both the Edit: Also, when you use the Lua script to set |
For all
Setting |
Ok, this is what I was afraid of. I believe Try this one and see if it makes the newer d3d8.dll look more like the legacy one: HRESULT STDMETHODCALLTYPE Direct3DDevice8::SetLight(DWORD Index, const D3DLIGHT8 *pLight)
{
if (!pLight)
{
return D3DERR_INVALIDCALL;
}
D3DLIGHT8 LightEdit;
memcpy_s(&LightEdit, sizeof(LightEdit), pLight, sizeof(LightEdit));
if (LightEdit.Type == D3DLIGHTTYPE::D3DLIGHT_SPOT)
{
if (LightEdit.Phi >= LightEdit.Theta)
{
LightEdit.Theta = 0.0f;
LightEdit.Falloff = LightEdit.Falloff * (1.0f + (LightEdit.Theta / LightEdit.Phi));
}
}
return ProxyInterface->SetLight(Index, &LightEdit);
} |
Do I have to load the scene with the 16x AF and 8x AA enabled from d3d8? |
You could enable AF and AA from d3d8 if you like. Then you can use d3d8to9 to covert that to d3d9. I do plan to look at the code and see if I can see any issues with dxwrapper's AF that could cause this issue. |
Sorry for the delay but I'm currently very busy studying for an upcoming exam. I'll provide the PIX files as soon as I can. |
I just tried making a GPU capture with PIX while Freelancer is running. Unfortunately it didn't work because the game is x86 and PIX only supports x64 apps from what I could find. Is there anything else I can try? |
Yeah, you need the old version of PIX. The new one doesn't work on DirectX9 or 32-bit applications. You need to download the old June 2010 SDK. Then you should be able to find the old version of PIX there. See this site. Once I installed the June 2010 SDK I found PIX here:
|
Here they are: PIX.zip. Both captures were made with AF and AA enabled from DxWrapper. The |
In both of these cases the game is using texture stage The weird thing is that in the GTX capture these function calls were completely missing. I am not sure what could cause these calls to be completely missing. It is almost like something caused the game to decide not to do any stage
What wrapper did you use to force 16x AF? How exactly did you use the wrapper to force this? |
You could try this update, I'm not sure it will help, but it is worth a try; dxwrapper.zip |
I used the d3d8 wrapper from your DirectX Wrappers project. As for the 16x AF, I simply updated the HRESULT m_IDirect3DDevice8::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
{
if (Type == D3DTSS_MAGFILTER)
Value = D3DTEXF_ANISOTROPIC;
if (Type == D3DTSS_MINFILTER)
Value = D3DTEXF_ANISOTROPIC;
if (Type == D3DTSS_MIPFILTER)
Value = D3DTEXF_ANISOTROPIC;
if (Type == D3DTSS_MAXANISOTROPY)
Value = 16;
return ProxyInterface->SetTextureStageState(Stage, Type, Value);
} I know you're not supposed to force-enable AF this way, but I just did it as a test.
With this build the textures do seem to load on the GTX PC. Well done! However, I just noticed that the AF doesn't seem to be working (this is also the case with the previous DxWrapper build): |
Ok, this means that the GTX you have does not support multi-staged AF textures. I made a simple change to turn off AF if multi-staged AF was not supported. I'm not sure the best way to turn off AF only when actually drawing multi-staged textures. |
Ok, try this one. I have it disable AF only when a multi-stage texture is actually set. dxwrapper.zip |
Same result as with the last build. Could have something to do with the GPU. |
Ok, can you try with one more update? dxwrapper.zip Also, please upload your log files for both systems. |
Unfortunately still no AF on the GTX 1050 laptop as far as I could tell. Here are the logs: |
Ok, I think this is the best we can get: dxwrapper.zip Can you try this one and let me know how it works on both systems? Does AF work? Are there any missing textures? Etc. Thanks for your help here! |
Alright, so on the RX 5700 PC all the textures loaded just fine, AA and AF both worked (same result as with the previous builds). On the GTX 1050 laptop however, the detail and emission textures appeared to be invisible again, as opposed to the last three builds. AA seemed to work fine though, but not AF. |
Ok, that is not what I expected. I don't think there is anyway I can get the GTX 1050 to work with AF and support those textures on d3d9. Try one more build. I hope this is the last: dxwrapper.zip |
With this build the emission and detail textures didn't work on the GTX 1050, neither did AF. Additionally, this time the AF option stopped working on the RX 5700 as well.
Oh well, at least the detail and emission textures can be loaded, so that's definitely an improvement! |
Too bad! I was hoping I would not need to make this more complicated. Ok, thanks for trying all these. I hope this one works correctly. It is similar to the second one I gave you. Can you try this one: dxwrapper.zip Note: the issue here is that I need to account for cube and volume textures, which makes it more complex. The first testing ones I gave you did not account for that. |
Alright, this is an interesting one. With the RX 5700, everything works fine. On the GTX 1050 however, the detail and emission textures seem to load at first, but after Alt-Tabbing and reloading the scene, they're no longer there. I didn't notice this behavior with the second build. Edit: |
Ok, I was just thinking I might need to reset it. Try this one to see if this is fixed: dxwrapper.zip
From the logs it looks like the GTX supports multi-stage AF for MinFiltering but not for MagFiltering. This could be why it looks like it is very low sample rate. |
Great, the issue has been fixed with the newest build. Tested it on both the RX 5700 and GTX 1050; couldn't find any new issues. |
Ok, here is the final build. I integrated all the fixes in. If you don't mind testing one last time I would be grateful: dxwrapper.zip |
Of course! Seems to work ok on both systems. |
Great! Thanks for all your help here! |
I'm trying to run a game with a d3d8.dll from an older Windows 10 version that fixes some lighting-related issues the game has with the default Windows 10 d3d8.dll. Additionally, I'd like to wrap the older d3d8.dll with d3d8to9 so I can enable AF and AA.
This is what I have in my game folder:
dxwrapper.dll
dxwrapper.ini
with the following config:This file includes all the other values in the default
dxwrapper.ini
file, but those have not been changed from their defaults.d3d8.dll
from the Stub folderd3d8.ini
with the following config:Custom\d3d8.dll
. This is the custom d3d8.dll that I want to load instead of the default Windows 10 one.With all these files and configs, d3d8to9 seems to load since the AF and AA are both working. However, it also seems the default Windows 10 d3d8.dll has loaded instead of the custom one, since the lighting bug is present in the game.
When I change
D3d8to9
indxwrapper.ini
from1
to0
, the exact opposite happens; the custom d3d8.dll loads, which has resulted in the lighting bug being gone, but obviously now d3d8to9 doesn't load as there is no AF nor AA.It seems like I can only get one or the other to work simultaneously, but I'd like d3d8to9 to wrap the custom d3d8.dll. Am I missing something or is it impossible to get the result I'm trying to achieve here?
I'm using DxWrapper v1.0.6542.21. (latest release)
The text was updated successfully, but these errors were encountered: