danoon2 / Boxedwine

Emulator that can run 32-bit Windows programs/games on multiple platforms via Wine
GNU General Public License v2.0
768 stars 66 forks source link

Add DIrectx11/12 support and port to UWP for Xbox One dev Mode #5

Open danprice142 opened 3 years ago

danprice142 commented 3 years ago

As this is openGL it wont work on xbox one and above could direct x be added and then Boxedwine turned into a uwp/appx to allow it to work on xbox one?

kickturn commented 3 years ago

Seems interesting and I would like to see this but as you said it can only run directx and not OpenGL but performance could be good looking at how emulation works on dev mode especially on the series consoles

danoon2 commented 3 years ago

Boxedwine runs Wine by proving an emulated CPU and emulate Linux Kernel. So Wine thinks its running on a 32-bit Linux system. Wine translates DirectX to OpenGL, then Boxedwine intercepts and marshals the OpenGL calls from the emulated program to the host computer. To do this I replaced the Linux version of libGL and created 1400 functions (lots of GL extensions) in there to do the forwarding for each one.

I think it would be possible to replace the Wine version of the DirectX libraries and forward those calls to the host, but this sounds like a huge project.

danprice142 commented 3 years ago

I posted this on a RetroArch for Xbox Discord channel and it got loads of likes in 5 mins before we all realized it wouldn`t work how it is. I believe that even though this is a lot of work i feel like it could have a serious demand also if it works for xbox it will work on windows as a store app. The Xbox Support DirectX11/12 and has ANGLE too if that helps?

Ryan14411 commented 3 years ago

I too would like this i so hope you do end up making the changes needed to get this working on the Xbox. keeping my fingers crossed. / And Thanks for Boxedwine im loving it!

Ryan14411 commented 3 years ago

https://www.theverge.com/2021/4/20/22393655/microsoft-windows-app-store-overhaul-apps-games-rumor

https://www.youtube.com/watch?v=f8_nvJzuaSU

https://devblogs.microsoft.com/commandline/the-initial-preview-of-gui-app-support-is-now-available-for-the-windows-subsystem-for-linux-2/

It uses Microsoft's own OpenGLOn12, by the way, which is an open source implemention of OpenGL, not proxying so i dont know if this will help making it a uwp for xbox but i think it will

danprice142 commented 3 years ago

I found something interesting and may be pretty useful to you and may possibly work to bring boxed wine to UWP https://github.com/gfx-rs/portability https://www.khronos.org/blog/khronos-announces-the-vulkan-portability-initiative

danoon2 commented 3 years ago

@danprice142 This one also looks interesting, and I was able to get it to work on Windows 10.

https://docs.mesa3d.org/drivers/d3d12.html

It converts OpenGL to Direct 3D 12.

danprice142 commented 3 years ago

Nice, do you think these layers would dramatically cut out most of the work to bring Boxed Wine to UWP?

danoon2 commented 3 years ago

I looked up more info on XBox One and it seems like XBox doesn't support dynamic code generation, at least according to this article

https://unity.com/how-to/develop-console-video-games-unity

In theory, Boxedwine could ahead of time recompile a particular game, but currently I don't have this feature.

danprice142 commented 3 years ago

Im almost 100% sure it does, i think this applies building in Unity im sure retroarch in dev mode uses it, i just asked another dev

danprice142 commented 3 years ago

https://github.com/bminor/SDL/blob/master/docs/README-winrt.md this could maybe make things easier

toastmod commented 2 years ago

What I've gathered from this thread is that wine's DX to OpenGL translation layer should probably be modified to call DX directly in UWP, I think that is the most optimal thing. Your other option is DX->OpenGL->ANGLE->DX which is super inefficient but would get the job done. I personally haven't had luck with ANGLE on Xbox but I didn't try overly hard either. So I think taking a look at the wine source and figuring out where that translator is might be the best solution here.

danoon2 commented 2 years ago

It would be interesting to see if someone might attempt this port. These things can take a shockingly large amount of time. I've been working on the x86 Mac port for the last year. It's pretty close, but there is always one more issue. After that I plan to attempt the Mac M1 port.

dinkeytomltd commented 2 years ago

I'm not sure if this is available on Xbox, but it is listed in the minimum requirements. It helped me run Boxedwine x64, Blender 3D and Sketchbook Pro on my Surface Pro X which doesn't have OpenGL drivers. Only downside is that it supports up to OpenGL 3.3. I wish I could help on this project, but what I want to contribute is way over my knowledge when it comes to Virtualization.

toastmod commented 2 years ago

I'd like to ask a little explanation on the source code here, where is wine per say in this source code? Where in the build process is wine included? I'd like to start researching the whole DX12 passthrough idea on my own time.

toastmod commented 2 years ago

So far I can see something interesting here, this seems to be where the D3D12 dll is written directly into Vulkan, however looking at the code for D3D11 the process seems to be a lot different. This is probably because D3D12 is supposedly very similar to Vulkan. I'd like to learn more about what you went through to create your OpenGL passthrough driver for wine.

So basically in order to do Wine <-> UWP I would make a libD3D12 for linux built the same way your marshalling libGL was built but instead bridge it to UWP somehow. Then I would implement this libD3D12 into the source code I linked above through thunks, like how Vulkan is marshalled to the linux Vulkan library somewhere around here..

I don't know how thunking entirely works yet but I would like to look into it if I have the time. So there's some stuff to think about I guess.

danoon2 commented 2 years ago

@toastmod I'm currently in the process of implementing vulkan pass through

The first step is to get the call out of the emulator and into boxedwine with a stub/proxy, like what you mentioned with my libGL implementation

https://github.com/danoon2/Boxedwine/tree/james/vulkan/tools/vulkan

Then you need to intercept the call in Boxedwine like I do with OpenGL

https://github.com/danoon2/Boxedwine/blob/e7e5a363c145e23a3c1b6a2d717b7c59750c8aaa/source/emulation/cpu/x64/x64Ops.cpp#L1153 https://github.com/danoon2/Boxedwine/blob/e7e5a363c145e23a3c1b6a2d717b7c59750c8aaa/source/emulation/cpu/normal/normal_other.h#L203

You could try using int 9b for D3D pass through, each CPU emulation will need some code to forward that instruction

The decoder will also need a small update https://github.com/danoon2/Boxedwine/blob/e7e5a363c145e23a3c1b6a2d717b7c59750c8aaa/source/emulation/cpu/decoder.cpp#L3644

The hard part is the marshaling. Boxedwine only emulates 32-bit programs, so if you want to run on a 64-bit platform, then your API you want to pass through will will need some work. Some data types might be a different size on the 64-bit platform.

See

https://github.com/danoon2/Boxedwine/blob/master/source/opengl/glMarshal.h

For ideas on how to marshal on 32-bit and 64-bit platforms.

Simple structures that contains no pointers and all the members are the same size just need to get the real address from the emulated address (getPhysicalAddress)

The hardest part I haven't fully solved, is if the API returns back a pointer that points to read/write memory, like mapping memory functions.

rodrigoandrigo commented 2 years ago

https://devblogs.microsoft.com/directx/in-the-works-opencl-and-opengl-mapping-layers-to-directx/ this may help

Pedro1234-code commented 1 year ago

guys is there something new here, like, it is still open?

danprice142 commented 5 months ago

Its been a while since I comented on this but I found something interesting https://github.com/aerisarn/mesa-uwp https://github.com/aerisarn/glxgears-uwp I have been talking to the dev and I know he has successfully got Mesa running in the Duckstation UWP emulator using OpenGL sucessfully on Xbox, as well as another emulator I can mention just yet, but that is two successfull tests

aerisarn commented 4 months ago

I was able to run this over Mesa UWP port with GL3 imgui. The main issue is that UWP doesn't support allocation on READ_WRITE_EXECUTE. With its codegen permission you can only call VirtualProtect over a page and put it in READ_EXECUTE mode, so the generator would have to fill a page and protect it before executing. From a quick glance, the memory allocation inside the binary translation would not support that as it's not exactly organized as pages. @danoon2 any suggestion?

danoon2 commented 4 months ago

@aerisarn That is interesting. You are correct. The current binary translator wants to generate the code in small increments.

I can only think of 2 solutions for this

1) change the code so that it will generate as much code as possible to fill a page when code is missing. So for all branches where it jumps to a known location, just keep translating.

2) Allow the code to fall back to the normal emulation (no binary translation). I might get to something like this later this year. It's hard for me to know for sure. One goal of mine has been to improve the web (WASM/emscripten) version of Boxedwine by introducing a WASM JIT. But there is probably a limit to how many WASM pieces of code I can generate at run time, so I would have to batch them up. I was thinking of making the normal CPU emulation multi-threaded then allow the JIT to run on that.

For performance, #1 would probably be better. The downside is if a page can't be filled then it would waste memory.