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

Metal Graphics Backend #6385

Closed
wants to merge 41 commits into from
Closed

Metal Graphics Backend #6385

wants to merge 41 commits into from

Conversation

stenzek
Copy link
Contributor

@stenzek stenzek commented Feb 17, 2018

Off topic comments not related to testing and feedback will be strictly moderated.

This branch introduces (yet another) backend to Dolphin: Metal. It is largely a work-in-progress, and several features are missing. The main motivation of developing this backend was to ensure the new videocommon interface design provided sufficient capabilities to move the majority of logic currently in the backends to common code.

Thus, the Metal backend has the abstract framebuffer and pipeline branches as prerequisites. All functionality is built using these primitives, avoiding any Metal-specific code where possible, outside of the derived abstract classes themselves.

Rather than mixing Objective C and C++, I used a C++ metal wrapper library (mtlpp). This in my opinion improves code clarity, and also has the benefit of handling object lifetimes, removing the need to sprinkle release and retain calls all over the source.

These two reasons are why the diff line count is huge. The backend itself is only around 5k lines. I'm not expecting anyone to review it just yet, at least not until the prerequisites are merged.

The changes to shadergen are rather intrusive, in some ways the code we were generating did not fit well with the Metal shading language. Perhaps there is a better way to support all the languages, aside from using an external translator.

Also, being a heavier language (C++-based), shader compilation "stutter" is likely worse than OpenGL, ubershaders and UID caches will be the solution here. But these will be implemented in common rather than the backend, so until that happens the backend will not support ubershaders.

Rough TODO list is as follows:

  • Support emitting MSL texture conversion shaders
  • Support emitting MSL vertex/pixel shaders
  • Basic rendering support in Metal backend
  • Abstract object implementations (texture/framebuffer/pipeline/staging texture)
  • Stream buffer implementation
  • State tracking
  • EFB to texture and RAM
  • Design a solution to render lines/points without geometry shaders (VS instancing perhaps?)
  • Figure out a way to get uncapped framerates (present skipping based on notifications from display link?)
  • Multisampling support
  • Bounding box/SSBO support
  • Ubershader/async pipeline compilation - this will be implemented in common
  • CPU EFB access (efb "peeks"/"pokes") - this will be implemented in common
  • Post processing - this will be implemented in common
  • Improve and optimize performance
  • Bug fixes

@stenzek stenzek added the WIP / do not merge Work in progress (do not merge) label Feb 17, 2018
This is needed to differentiate between the open-source Mesa drivers and
their binary counterparts for Intel and AMD.
@microbug
Copy link

A more-or-less drop-in solution (as far as I know) has just become available: https://www.anandtech.com/show/12465/khronos-group-extends-vulkan-portability-with-opensource.

It's not often we switch out to draw to the EFB anyway.
Since we use the common pipelines here and draw vertices if a batch is
currently being built by the vertex loader, we end up trampling over its
pointer, as we share the buffer with the loader, and it has not been
unmapped yet. Force a pipeline flush to avoid this.
We would want to improve the granularity here in the future, but for
now, this should avoid any performance loss from switching to the
VideoCommon shader cache.
As these are stored in a map, operator< will become a hot function when
doing lookups, which happen every frame. std::tie generated a rather
large function here with quite a few branches.
@stenzek
Copy link
Contributor Author

stenzek commented Mar 3, 2018

Line count has grown even further due to now depending on 6 related branches. The actual backend itself is only +5000 lines.

I've also switched from generating MSL directly to generating GLSL, then SPIR-V, and using SPIRV-Cross to translate these shaders to MSL. This means that we don't need to significantly modify shadergen, as the changes there were quite intrusive.

This means the Metal backend now supports ubershaders, although performance could be terrible, I haven't really benchmarked it. Oh, and you should be able to get framerates above 60fps now. I've implemented psuedo-triple-buffering, it's not ideal, but seems to work fine.

@stenzek
Copy link
Contributor Author

stenzek commented Mar 3, 2018

@microbug I suspect that going via MoltenVK will be slower than this backend, as there is a considerable difference in the API versus Vulkan, which requires translation. But feel free to make a PR integrating MoltenVK and prove me wrong ;)

I did try for laughs a while back, and I couldn't get the swap chain functioning. Entirely possible I did something wrong though. Also you won't be able to get a higher frame rate than the screen refresh with MoltenVK.

@microbug
Copy link

microbug commented Mar 4, 2018

@stenzek I'm nowhere near experienced enough to make a PR integrating MoltenVK. Just thought it might be useful, but a (faster) native Metal backend is of course preferable.

This doesn't mean the resulting binaries will require 10.13
to run, however, it enables us to use the new Metal functions
introduced in 10.13.
Works around the cached value in the buildbots of 10.9
@dolphin-emu dolphin-emu deleted a comment from christ776 Apr 22, 2018
@pizuz
Copy link

pizuz commented Aug 1, 2018

Just gave this build a spin. Looks quite stable.

Twilight Princess fails to render the mini-map and therefore runs at full speed. Also glitches galore (water overlay effects being opaque, sense mode producing a white screen ).
Mario GalaxySunshine runs quite well, aside lots of flickering and glitching textures.
Wind Waker runs well aside a few depth issues.

EDIT: Some more testing revealed some performance differences in Twilight Princess regarding the Hyrule Field Slowdowns (Post-Lanayru Spring):

OpenGL: 15 VPS
MoltenVK (10.0.17): 25 VPS
Metal: 3545 VPS (glitches aside)

Interestingly Metal and Vulkan cap GPU usage at about 70% during those phases, while OpenGL produces close to 100% GPU usage. All four physical CPU cores get about 30% load equally (Hyperthreading doesn't seem to be active, apparently)

Setup: 3.1 GHz Haswell i7 and GeForce 750M in a late 2013 iMac running macOS 10.13.6

So, basically yes, MoltenVK is slower than pure Metal (dunno the impact of the graphics not rendering properly). Will test it against Windows, if I get to it.

@MrGcGamer
Copy link

When will we see the metal backend get implemented in Dolphin? Or is something like a beta already out? (I have a MakBookPro mid2010 so Wind Waker runs terribly with opengl and I don’t know how to improve the performance and than I heard a Metal backend is in work)

@lukearnould
Copy link
Contributor

lukearnould commented Aug 6, 2018

This pull request has been indefinitely postponed, but stenzek is working on a Vulkan backend for macOS using MoltenVK that should offer much improved performance compared to OpenGL.

@MrGcGamer
Copy link

Do you know how long it’s probably going to take until it’s finished?

@lukearnould
Copy link
Contributor

@MrGcGamer It's making good progress, you can follow it here: #7039

@MrGcGamer
Copy link

One little question left is my mac supported for moltenvk (geforce 320m)?

@lukearnould
Copy link
Contributor

@MrGcGamer After some searching it seems your MacBook doesn't support Metal. Per this article the cutoff for Metal support is the NVIDIA GTX 400 series GPUs. Your GPU is one generation too old.

No Metal means no MoltenVK either (because that essentially wraps Vulkan to be run under Metal).

So whether a native Metal backend or a MoltenVK backend were to be implemented, either way your computer would not support it.

I'm sorry. There's nothing the Dolphin developers can do about it.

@moda20
Copy link

moda20 commented Aug 12, 2018

This is probably not the best place to ask, but I am running dolphin on high Sierra (hackintosh) and i have a huge lag even with native resolution and minimum graphics. will the metal graphics backend help fix this ? and I still can't see it when choosing backends on config.

@lukearnould
Copy link
Contributor

lukearnould commented Aug 12, 2018

@moda20 The Metal backend isn’t completed yet, that’s why you can’t select it. Even if you downloaded a build of this pull request, it probably wouldn’t be usable due to bugs.

If the Metal backend is completed it will give much improved performance. However this pull request is indefinitely postponed, so I’d be watching this other pull request that’s working to implement a Vulkan backend on macOS using MoltenVK: #7039. It will still be a big performance improvement, but not quite as good as a native Metal backend.

In the meantime you could try asynchronous shaders in the ubershader graphics options. But since you’re running a hackintosh anyway, you’re best off using Dolphin on Linux or Windows. That’s the only way you’ll get decent performance anytime soon.

@cesar18pena
Copy link

@stenzek do you have an idea about how much time is PR is gonna by postponed? I try using this PR version with Metal backend, I tested the games Wind Waker and Metroid Prime 2 and I could see a big improvement(really big) in Mac OS X.

This work is amazing, I hope you could complete this PR, even after Vulcan for MacOS to improve greatly gameplay in MAC.

PD: Are there specifics trainings or documentations that you recommend to understand and use C++ and Metal. To help and create a better dolphin for Mac users.

@stenzek
Copy link
Contributor Author

stenzek commented Aug 13, 2018

MoltenVK is the solution for now. I simply don't have the time to maintain another backend, even if I did complete the missing features.

At some point in the future I may resurrect this branch, but for now it's dead. If someone does want to pick it up, there's an untested/rebased version in stenzek/metal.

@stenzek stenzek closed this Aug 13, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
WIP / do not merge Work in progress (do not merge)
Development

Successfully merging this pull request may close these issues.

7 participants