Skip to content
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

Build with wineg++ wrapper #60

Closed
pchome opened this issue Feb 5, 2018 · 13 comments
Closed

Build with wineg++ wrapper #60

pchome opened this issue Feb 5, 2018 · 13 comments
Labels

Comments

@pchome
Copy link
Contributor

pchome commented Feb 5, 2018

I'm trying to build project w/ wineg++ but it seems only tests/* executables wrapped correctly. Both d3d11.dll.so and dxgi.dll.so are useless and produce errors when I'm trying to replace original libraries :

...
uild.w64_5\tests\dxgi\dxgi-factory.exe.so: malloc.c:2399: sysmalloc: Assertion `(old_top == initial_top (av) && old_size == 0) || ((unsigned long) (old_size) >= MINSIZE && prev_inuse (old_top) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
err:seh:call_stack_handlers invalid frame 7ffea8fc25c0 (0x132000-0x230000)
err:seh:NtRaiseException Exception frame is not in stack limits => unable to dispatch exception.

[221151.875587] d3d11-triangle.[6933]: segfault at 366 ip 0000000000000366 sp 00007ffc3ed84bf8 error 14 in bash[55f36b668000+e4000]

So the question is: Is it possible to build WINE's native linux libraries to replace original ones? Or i'm doing this totally wrong and really need to configure crossdev environment w/ mingw32?

Here is the list of changes was made :
build-win64-wine.txt

[binaries]
c = '/usr/bin/winegcc'
cpp = '/usr/bin/wineg++'
ar = '/usr/bin/ar'
strip = '/usr/bin/strip'
exe_wrapper = 'sh'

[properties]
c_args = ['-m64', '-DNOMINMAX', '-DWINEBUILD']
c_link_args = ['-mwindows', '-lpthread']

cpp_args = ['-m64', '-DNOMINMAX', '-DWINEBUILD']
cpp_link_args = ['-mwindows', '-lpthread']

[host_machine]
system = 'linux'
cpu_family = 'x86_64'
cpu = 'x86_64'
endian = 'little'

actually -mwindows required only by tests/* and -lpthread by d3d11.dll.so and dxgi.dll.so

meson.build.wine

project('dxvk', ['c', 'cpp'], default_options : ['cpp_std=gnu++1z'])

cpu_family = target_machine.cpu_family()

dxvk_compiler = meson.get_compiler('cpp')
dxvk_include_path = include_directories('./include')

lib_d3d11          = dxvk_compiler.find_library('d3d11')
lib_dxgi           = dxvk_compiler.find_library('dxgi')
lib_d3dcompiler_47 = dxvk_compiler.find_library('d3dcompiler')
lib_vulkan         = dxvk_compiler.find_library('vulkan')

glsl_compiler = find_program('glslangValidator')
glsl_generator = generator(glsl_compiler,
  output    : [ '@BASENAME@.h' ],
  arguments : [ '-V', '--vn', '@BASENAME@', '@INPUT@', '-o', '@OUTPUT@' ])

subdir('src')
subdir('tests')
subdir('wine_utils')

Other quick-fixes:

diff --git a/src/d3d11/d3d11_include.h b/src/d3d11/d3d11_include.h
index 54d3a1d..beed12f 100644
--- a/src/d3d11/d3d11_include.h
+++ b/src/d3d11/d3d11_include.h
@@ -24,6 +24,7 @@
 // For some strange reason, we cannot use the structures
 // directly, although others from the same header work.
 // Some structures are missing from the mingw headers.
+#ifndef WINEBUILD
 typedef struct D3D11_FEATURE_DATA_THREADING {
     BOOL DriverConcurrentCreates;
     BOOL DriverCommandLists;
@@ -58,4 +59,9 @@ typedef struct D3D11_QUERY_DATA_PIPELINE_STATISTICS {
   UINT64 HSInvocations;
   UINT64 DSInvocations;
   UINT64 CSInvocations;
-} D3D11_QUERY_DATA_PIPELINE_STATISTICS;
\ No newline at end of file
+} D3D11_QUERY_DATA_PIPELINE_STATISTICS;
+#endif
+
+#ifdef WINEBUILD
+typedef BOOL WINBOOL;
+#endif
diff --git a/src/d3d11/meson.build b/src/d3d11/meson.build
index e96ff92..62ae468 100644
--- a/src/d3d11/meson.build
+++ b/src/d3d11/meson.build
@@ -22,7 +22,7 @@ d3d11_src = [
   'd3d11_util.cpp',
 ]
 
-d3d11_dll = shared_library('d3d11', d3d11_src,
+d3d11_dll = shared_library('d3d11.dll', d3d11_src,
   name_prefix         : '',
   link_with           : [ util_lib ],
   dependencies        : [ dxvk_dep, dxgi_dep, dxbc_dep ],
diff --git a/src/dxgi/dxgi_include.h b/src/dxgi/dxgi_include.h
index 87fd945..8720c8d 100644
--- a/src/dxgi/dxgi_include.h
+++ b/src/dxgi/dxgi_include.h
@@ -26,4 +26,8 @@
   #define DXGI_RESOURCE_PRIORITY_NORMAL (0x78000000)
   #define DXGI_RESOURCE_PRIORITY_HIGH (0xa0000000)
   #define DXGI_RESOURCE_PRIORITY_MAXIMUM (0xc8000000)
-#endif
\ No newline at end of file
+#endif
+
+#ifdef WINEBUILD
+#define _countof(x) (sizeof(x)/sizeof(x[0]))
+#endif
diff --git a/src/dxgi/dxgi_output.cpp b/src/dxgi/dxgi_output.cpp
index a2a26dc..e96f82a 100644
--- a/src/dxgi/dxgi_output.cpp
+++ b/src/dxgi/dxgi_output.cpp
@@ -58,7 +58,7 @@ namespace dxvk {
     ::MONITORINFOEX monInfo;
 
     monInfo.cbSize = sizeof(monInfo);
-    if (!::GetMonitorInfo(m_monitor, &monInfo)) {
+    if (!::GetMonitorInfo(m_monitor, (MONITORINFO *)&monInfo)) {
       Logger::err("DxgiOutput: Failed to query monitor info");
       return E_FAIL;
     }
@@ -86,7 +86,7 @@ namespace dxvk {
     ::MONITORINFOEX monInfo;
 
     monInfo.cbSize = sizeof(monInfo);
-    if (!::GetMonitorInfo(m_monitor, &monInfo)) {
+    if (!::GetMonitorInfo(m_monitor, (MONITORINFO *)&monInfo)) {
       Logger::err("DxgiOutput: Failed to query monitor info");
       return E_FAIL;
     }
diff --git a/src/dxgi/meson.build b/src/dxgi/meson.build
index f58b132..dc0c2f7 100644
--- a/src/dxgi/meson.build
+++ b/src/dxgi/meson.build
@@ -9,7 +9,7 @@ dxgi_src = [
   'dxgi_swapchain.cpp',
 ]
 
-dxgi_dll = shared_library('dxgi', dxgi_src,
+dxgi_dll = shared_library('dxgi.dll', dxgi_src,
   name_prefix         : '',
   link_with           : [ util_lib ],
   dependencies        : [ dxvk_dep ],
diff --git a/src/util/com/com_guid.h b/src/util/com/com_guid.h
index 510fd0c..ce80c2e 100644
--- a/src/util/com/com_guid.h
+++ b/src/util/com/com_guid.h
@@ -4,7 +4,12 @@
 
 #include "com_include.h"
 
+#ifdef WINEBUILD
+#define DXVK_DEFINE_GUID(iface) \
+  template<> inline GUID const& __wine_uuidof<iface> () { return iface::guid; }
+#else
 #define DXVK_DEFINE_GUID(iface) \
   template<> inline GUID const& __mingw_uuidof<iface> () { return iface::guid; }
+#endif
 
 std::ostream& operator << (std::ostream& os, REFIID guid);

EDIT: typo useful/useless

@doitsujin doitsujin added the build label Feb 5, 2018
@Guy1524
Copy link
Contributor

Guy1524 commented Feb 5, 2018

Hey, I have been working on this for the past two days. I managed to get it to build, and now I am working on runtime issues. A lot of my solutions are lot less clean than yours though.

As for your current problem, it has to do with windows strings. If you replace both of the functions in util_env.cpp with return ""; it bypasses the issue. Also, you might want to remove the dll override thing, because it stops the backtrace from showing up, which is how I found the solution to that problem

By the way, if you want to discuss this further, you might want to get on the discord.

EDIT: The Vkx discord (https://discord.gg/C8EEVmy)

@pchome
Copy link
Contributor Author

pchome commented Feb 5, 2018

If I understand correctly it must be something like :

diff --git a/src/util/util_env.cpp b/src/util/util_env.cpp
index 0464bc3..f5f7fd8 100644
--- a/src/util/util_env.cpp
+++ b/src/util/util_env.cpp
@@ -5,6 +5,7 @@
 namespace dxvk::env {
 
   std::string getEnvVar(const wchar_t* name) {
+#ifndef WINEBUILD
     DWORD len = ::GetEnvironmentVariableW(name, nullptr, 0);
     
     std::wstring result;
@@ -17,10 +18,14 @@ namespace dxvk::env {
     
     result.resize(len);
     return str::fromws(result);
+#else
+    return "";
+#endif
   }
   
   
   std::string getExeName() {
+#ifndef WINEBUILD
     std::wstring exePath;
     exePath.resize(MAX_PATH + 1);
     
@@ -33,6 +38,9 @@ namespace dxvk::env {
     return (n != std::string::npos)
       ? fullPath.substr(n + 1)
       : fullPath;
+#else
+    return "";
+#endif
   }
   
 }

Ok, with this I have following output:
$ WINEDEBUG="+loaddll" ./d3d11-triangle.exe

...
trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\user32.dll" at 0x7feca1990000: builtin
trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\dxgi.dll-60mFyb.spec" at 0x7feca2070000: builtin
trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\d3d11.dll-8gpwHe.spec" at 0x7feca0e30000: builtin
trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\d3dcompiler_43.dll" at 0x7feca0b70000: builtin
trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\imm32.dll" at 0x7feca06e0000: builtin
trace:loaddll:load_builtin_dll Loaded L"C:\\windows\\system32\\winex11.drv" at 0x7feca0430000: builtin
wine: Call from 0x7bc853ac to unimplemented function dxgi.dll.CreateDXGIFactory, aborting
fixme:seh:dwarf_get_ptr unsupported encoding 9b
fixme:seh:dwarf_get_ptr unsupported encoding c1
fixme:seh:dwarf_get_ptr unsupported encoding 9b
fixme:seh:dwarf_get_ptr unsupported encoding c1
err:seh:call_stack_handlers invalid frame 20062 (0x132000-0x230000)
err:seh:NtRaiseException Exception frame is not in stack limits => unable to dispatch exception.

It looks like .spec file needed for build or .fake build or both. At least wine attempting to load them.

@Guy1524
Copy link
Contributor

Guy1524 commented Feb 5, 2018

I solved this issue a few hours ago, you need to build with a spec file.

dxgi.spec:
@ stdcall CreateDXGIFactory(ptr ptr)
@ stdcall CreateDXGIFactory1(ptr ptr)

d3d11.spec
@ stdcall D3D11CreateDevice(ptr long ptr long ptr long long ptr ptr ptr)
@ stdcall D3D11CreateDeviceAndSwapChain(ptr long ptr long ptr long long ptr ptr ptr ptr ptr)

Then you need to add these to the LINK_ARGS when building

@ssorgatem
Copy link
Contributor

If I understand this correctly... with this we can build dxvk for Linux without relying on a cross-compiling environment, but just wine and gcc? (the end result being a wine library rather than a Windows dll)

That'd be really handy for Arch users building dxvk from the AUR.

@Guy1524
Copy link
Contributor

Guy1524 commented Feb 7, 2018

@ssorgatem While that is one result, the main reason is to allow profiling. On linux it is impossible to profile PE executables.

@pchome
Copy link
Contributor Author

pchome commented Feb 7, 2018

Ok, I found the problem.
I'm trying to link dxvk w/ libvulkan.so but it should be WINE's vulkan-1.dll.so :) The other problem that WINE don't provides libvulkan-1.def and libd3dcompiler_47.def and meson failed to find this libs.

So:

$ winebuild -w --def -o libd3dcompiler_47.def --export path/to/wine/dlls/d3dcompiler_47/d3dcompiler_47.spec -m64
$ winebuild -w --def -o libvulkan-1.def --export path/to/wine/dlls/vulkan-1/vulkan-1.spec -m64

than cp them somewhere meson will able to find them
and use original

lib_d3dcompiler_47 = dxvk_compiler.find_library('d3dcompiler_47')
lib_vulkan         = dxvk_compiler.find_library('vulkan-1')

With this changes I can successfully build and run tests.
$ WINEDLLOVERRIDES='d3dcompiler_47.dll=n' ./d3d11-triangle.exe - finally reveals window with triangles.

@Guy1524
Copy link
Contributor

Guy1524 commented Feb 7, 2018

Awesome!

By the way, for some reason when I use vulkan-1.dll.so, I get undefined reference to vkGetInstanceProcAddr, however when i use wine's vulkan.dll.so, it compiles find, and even somewhat works, before crashing due to some unrelated issue.

Anyway, when I do get it working with vulkan.dll.so, it crashes on a null function pointer. And maybe the reason of this is that you are compiling the tests natively as well. I am curious what would happen if you tried this dll with a PE d3d11-using executable.

@pchome
Copy link
Contributor Author

pchome commented Feb 8, 2018

I am curious what would happen if you tried this dll with a PE d3d11-using executable.

I have tested TW3 and it fails w/ Not implemented/Invalid blend/Unsupported program type errors in output. It's how it should be for now I guess. Other programs works as before even if have dependencies on d3d11 or dxgi.

@doitsujin
Copy link
Owner

If this actually works, can you make a pull request out of if?

@pchome
Copy link
Contributor Author

pchome commented Feb 15, 2018

I'm on it. But this requires build system modification and some problematic code dropping (e.g. env var support). Also I have no luck to build fully functional x86 version, maybe due to not portable memory management code.

Also I'm trying to do my best to keep current build system and project behaviour and minimize changes and dependencies required for linux build support. But I have some options I can play with:

  • use winebuild for compilation and link stages, it decides what params to pass to gcc and ld by itself but have some hardcoded paths to wine files which also different between 32 and 64 versions of winebuild and wine versions
  • use gcc for compilation and winebuild for linking like wine does by itself, more control and more changes required but almost the same as above
  • use gcc only - requires even more changes to build system and passing all parameters and definitions which winebuild passes by itself but provides full control on build process

Also *.spec and *.def files required on different build stages and need to be either present, generated or bundled. And therefore some parts like vulkan-1.dll.so present only in wine-staging but I have luck to successfully bundle and build vulkan libraries but all parts of project still connected by hands and requires a lot of interactions.

So I'm not sure you accept such PR but I'll create a separate branch in my repo and let you know.

@pchome
Copy link
Contributor Author

pchome commented Feb 16, 2018

@doitsujin branch name winebuild
pchome@e7102cc
pchome@e5027ce

@pchome
Copy link
Contributor Author

pchome commented Feb 16, 2018

I have set winebuild as default branch and added some options support.

  • Installed vulkan-1 don't required for build now, same for d3dcompiler_47, dxgi and d3d11.
  • env, utils and tests can be disabled via $ meson configure -Denv=false -Dutils=false -Dtests=false
  • DLL redirects support via -Ddll-redirects=true (builds libraries with _vk suffix)

Minimal requirement for functional build for now (due to crashes):

$ meson -Dwine-build=true --cross-file build-win64-wine.txt build.64
$ meson configure -Dprefix=/tmp/dxvk -Dbuildtype=release -Denv=false

Therefore

  • shader dump/read directories defaulted to dxvk_shader_dump and dxvk_shader_read
  • logs stored in current directory and prefixed w/ dxvk_
  • game-specific options affected too (not sure if they works or used)

@doitsujin if those commits are ok for you I can create PRs or grab everything your want by yourself
https://github.com/pchome/dxvk/commits/winebuild

@doitsujin
Copy link
Owner

64-bit winelib builds are now supported using the build-wine64.txt cross file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants