evmar / retrowin32

windows emulator
https://evmar.github.io/retrowin32/
Apache License 2.0
581 stars 24 forks source link

Builtin implementations of sdl2.dll + webgpu.dll #37

Open mateli opened 2 months ago

mateli commented 2 months ago

Create a sdl2 wrapper with WebGPU support and port sample applications that already works with emscripten. This would cover wasi-webgpu when using retrowin32 for web development.

Create both native and emulated dll's so that applications can be developed and run both in retrowin32 and 32 bit windows. Perhaps also wine?

evmar commented 2 months ago

I didn't really follow what this is requesting, can you elaborate?

mateli commented 2 months ago

If I compile the SDL2 samples to 32 bit windows executable will they load into retrowin32 will the sample load 32 bit sdl dll files and intercept calls to opengl? Or will they load host native dll files which for browsers could be the emscripten variant of SDL that can render using WebGL and WebGPU?

Currently there is no emulated sdl.dll or similar that I've been able to find in the retrowin32 source tree meaning that were not getting the speed of emscriptens SDL when running in a browser.

evmar commented 2 months ago

Ah I see, you're suggesting to provide a "builtin" version of these dlls, I get it!

I'm not sure, but I think it won't save you much performance. Right now if you had an app that used SDL, SDL would target DirectX, and retrowin32 does implement DirectX to (try to) map it to more efficient canvas calls. So there is some overhead in that we are running an emulated version of SDL, but SDL is mostly mapping to DirectX calls anyway, it is not much overhead. Most of the performance is spent in the graphics buffer-manipulation within DirectX.

mateli commented 2 months ago

SDL when compiled for Windows supports using OpenGL, DirectX, Vulkan or WebGPU.

While my personal priority is running stuff in the browser I will expand this discussion to cover other targets as well.

DirectX is default but cannot be used directly by the application/game so many developers instead use OpenGL. That is a problem in many different ways. One of them is that OpenGL is not consistent over time in the same way that other features of SDL. With retrowin32 I don't think that OpenGL is supported so that would obviously fail to run.

So to deal with different scenarios I am thinkin the following:

  1. Pure SDL. Here we have multiple choices. Running a w32 dll file that use a DirectX implementation that in a browser renders using WebGPU works. Creating an emulated library has two benefits here. One is that using a platforms native SDL library probably works without much work on a decent amount of host platforms. On Windows it would default to DirectX, on Linux to OpenGL and in the browser to WebGPU. On non-windows platforms (including browsers that run on windows) no DirectX needs to be involved at all.

  2. SDL + OpenGL. Here we also have multiple choices. Implementing WGL in a way that is compatible with compiled SDL libraries will work. For an emulated backends there are a bunch of choices. Emscripten provides robust OpenGL-to-WebGL translation which can be used for browsers. GL4ES can work on embedded devices. Zink can run OpenGL on top of Vulkan. And of course any platform with native OpenGL support can be supported more directly.

  3. SDL + WebGPU. This is rising in popularity due to it's exceptional portability and provides similar functionality to SDL + OpenGL. There are sdl2webgpu that is used with native WebGPU applications and Emscripten which is used for web applications. Obviously a win32 application would use sdl2webgpu so that is what we would need to support. Here we have multiple options again. WebGPU can as win32 dll files inside the emulator. Those dll files can be emulated and host webgpu ports can be used. And on a browser host a thin wrapper for Emscripten webgpu can be used. For rust there are wgpu that can be used to cover a sufficient amount of platforms without having to use different WebGPU implementations:s.

  4. SDL + Vulkan. This was rising in popularity before WebGPU stole the spotlight from Vulkan. Supporting this needs either hardware Vulkan support or a translation layer like MoltenVk. However when it comes to supporting Mac WebGPU seems to quickly becoming the popular choice when a multi-platform API is desired. So for applications that intend to support Windows, Mac, Linux, Browsers and mobile platforms WebGPU is probably more common for new projects than Vulkan. I do not know if any applications actually need this?

Other notes: Writing this I dug in to wgpu a bit and noticed that it does support browser WebGPU but it is not the emscripten sdl+WebGPU support. Using this to emulate wgpu as well as other WebGPU libraries in windows may be a way to run SDL+WebGPU. Following discussions on WebGPU and MoltenVk, the latter has the problem that it is very hard to get the same code to work on for example both AMD and Nvidia hardware. So the easiest way to get GPU applications to work on Mac is WebGPU which is a mayor reason why people are choosing it. Simply put while vulkan promises cross platform development it doesn't deliver on this like WebGPU does. This will of course have an impact on win32 as well as those that use WebGPU for mac are probably not going to chose a different API for Windows.

evmar commented 2 months ago

Bigger picture, if you have an app you are trying to run in a browser, compiling it for wasm will be a lot better performance than compiling it for x86. So the only applications retrowin32 is useful for are the older ones that are not targeting webgpu in the first place.

mateli commented 2 months ago

Bigger picture. If I want an app that is as fast as possible I write it in Python and run it outside of the browser on pretty much any platform. Way faster than any compiled wasm application and will usually run everywhere. That is true for a growing set of Python applications and is the reason for its huge growth. Probably not yet true for anything that would spend a lot of time running something like WebGPU but still very relevant. This is by the way something that I do so not just something taken out of the air. For Win32 applications that processes large amount of data I split them op in Win32 frontend and Python backend. In other cases where Python is not the fastest solution I instead use C# with System.Numerics.

It should be noted that I am not merely thinking about targeting browsers here. The advantage of WebGPU is that besides running in browser it also runs directly on Vulkan, Metal, D3D12, OpenGL, and WebGL2. So with any win32 application ported to WebGPU it would be possible to run it without any emulation layer, just like with OpenGL but with even more platform support.

For the fist statements sure if I limit my toolset to a small number of programming languages and write a new application from scratch then compiling for wasm is a great idea. Compiling to wasm+native is an even better idea. However with the current landscape I still have to compile more than once to target browsers, Windows, Linux and OS X. To achieve compile once and run everywhere can not yet be achieved with wasm nor does it seems to be in the plans of the developers that are making wasm. At the very best we are moving toward having one standard for browsers (existing web api's) and another for non-browsers (wasi). To achieve something that truly follows the "compile once run anywhere goal" I will still need some kind of abstraction level.

However to do that we need to add that if I do what is suggested above I do not only limit myself in what languages I can use. I also will have to reinvent large amounts of reusable win32 code that I could have pulled into my project but that will not fit into any wasm toolchain. Personally I have code written in C, C++, Delphi and Visual Basic (Classic) that even for the C/C++ code will not be easy to port to wasm.

The above mentioned steps can be bearable for new applications what about the old ones? The legacy win32 applications that are still maintained and developed. How many are they? It is hard to say as many of them are internal tools that are not publicly distributed. However if you go online and download random windows applications that have active development a lot of them are only available in win32 binaries. Porting them to x64 is about as difficult as remaking them in something more portable.

To run those applications on modern hardware that are not always x86-compativle qemu combined with wine has been the common solution because it works. It is even common on x64 because quite often the cost of having to switch the CPU between 32 bit and 64 bit is heavier than running qemu, naturally depending on the total balance of software running on the machine. And for some linux distributions getting multi-lib working is so problematic that people rater just put up qemu+32 bit-debian+wine. There are guides on how to set up a chroot with qemu running 32-bit debian only with the purpose of running wine in it.

So for the last statement I have to completely agree. And the large number of still maintained old applications this is easy to explain, there has historically been no benefit in using WebGPU. They have been porting to SDL+OpenGL because OpenGL is supported by wine. Although wine also has DirectX emulation it is has historically been secondary as OpenGL doesn't require an emulation layer (and possibly because OpenGL is easier). Although the discontinuation of OpenGL on OS X as I mentioned has brought some attention to WebGPU implementations that while codeweavers are figuring things out can run on top of wine's DirectX implementation.

So beating wasm in the browser may be difficult. But can retrowin32 beat Qemu+Wine for on being the fastest ARM (Mac, Raspberry Pi etc) executor of win32 applications that support WebGPU? Quite certainly. Can retrowin32 beat Qemu+Wine on actually working on ARM platforms? Even more certainly. Try getting Wine running on a Raspberry Pi if you are in doubt.