-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
D3D: Generate HLSL from SPIRV* #10673
Conversation
Please mind that macOS builds already include SPIRV-Cross as part of the MoltenVK dylib. |
3762387
to
92fe9c7
Compare
2b78cc0
to
2b5b554
Compare
This comment was marked as outdated.
This comment was marked as outdated.
Upstream review was merged, I opened a new PR for the external separately. This change is now ready for review and testing! |
Have you tested how this affects shader generation time? Best way I know to test this is by measuring frametimes while generating shaders but that could be a bit noisy. |
@Miksel12 - no I have not. I did eyeball the generation during my tests and didn't notice anything excessive. I am open to someone doing some more formal tests in this area. I wouldn't expect this to improve shader compilation times at all. DirectX still needs the shaders in its proprietary bytecode format, so converting GLSL -> SPIRV -> HLSL actually introduces a bit more overhead. The only advantage to be gained would be optimizing the SPIRV. That could come in the future but not sure if that would help or hurt compile times. @phire has mentioned that eventually we might be able to mitigate some of this overhead by doing this at build time but it's not clear to me how that would work. If the performance hit is too high, we can always scale back and just do this for our user-generated shaders but I was hopeful to reduce the maintenance overhead for Dolphin devs as well. |
Are you familiar with naga(https://github.com/gfx-rs/naga)? They tout very fast translation: https://gfx-rs.github.io/2021/05/09/dota2-msl-compilation.html and could even replace glslang. I have no idea how difficult it is to incorporate a Rust dependency or how production ready it is so maybe this is not feasible but it sounds promising. |
@Miksel12 - I hadn't heard of that but I don't think that would be a good fit. At least it doesn't look like they have any C bindings and I get the impression it's not as developed as SPIRV-Cross. If it was usable, I'd be willing to try it but not really sure I want to jump through a lot of hoops, SPIRV-Cross on the other hand is a C++ library. I talked with @phire and I guess I'm going to look at adding a shader compilation time statistic as a separate PR. I will then have a directly comparable metric with master to compare this with. |
I might be missing something here but doesn't this PR still contain the changes in #10698? |
@Zopolis4 - yes, at least other PRs I've seen in the past will split the external dependency out into a separate PR so that can be merged first, thus making the rest of the code easier to merge? |
No but like doesn't splitting out the external dependency mean you dont have it in the main PR? Or are you keeping it so everything builds correctly, and then will remove it once 10698 is merged? |
Yeah, if the other one gets merged first, I will update this. I'm keeping the external in this code base so people are able to test, or if this one gets merged first I can just close out the other. |
b5d98d7
to
9cdd552
Compare
After using #10706 on master and on this branch, the compilation impact is in. Compiling from GLSL -> DX bytecode (using SPIR-V) is roughly 30% slower than HLSL -> DX bytecode. This means that any shader stutter that exists would last 30% longer. I tested both hybrid and specialized shaders. The advantage as stated earlier is that all custom HLSL in Vertex, Pixel, and Compute shaders can be dropped. In the future, we could possibly look at writing raw SPIRV or @phire has floated the idea of generating these shaders at build time somehow. It seems most of our time spent is in the GLSL -> SPIRV stage ( > 75% of the time ). Given that we now have two backends using SPIRV (D3D, Vulkan) and one that could potentially use it (OGL 4.6), it may be beneficial to look into how to create that without needing GLSL. That is a much larger task however. I'd be curious to hear opinions from the rest of the dev team on this. |
d3ffcd7
to
edc8d79
Compare
I did some tests years ago and I've been using DX11 exclusively since then because it's the only backend that is stutter-free when using Hybrid (even though Vulkan gives me more FPS). So from a user's perspective this change hurts. Maybe you can regain some of the lost performance by generating the SPIR-V directly but otherwise this doesn't seem worth it (where VK = raw performance and DX11 = fastest shaders). |
This won't actually affect stuttering in Hybrid Ubershaders. It'll just mean that it uses the Ubershaders 30% longer in that case. If you didn't see a stutter before, it means that it was handing things off correctly already. |
Nothing new really. Just pushed up some cmake changes thanks to @TellowKrinkle ! |
I really haven't looked at this PR at all, but is there a chance it will allow removing glslang? glslang is the slowest code to compile in the entire codebase... (not that it's super important, but it seems like 1/2 the PRs these days are just adding new Externals) |
@shuffle2 - sorry to say I'll double disappoint you. First, this PR uses
|
OT but that's currently on the roadmap for Cemu. |
@Anuskuss - yeah. Thinking about that angle some more, I'll retract my statement. For more modern emulators it makes sense, since they are already dealing with shader instructions. For Dolphin, I'm not sure if it's reasonable. SPIRV is a low level representation of a shader and wouldn't really be nice to write or read the way Dolphin handles shaders. |
BTW if you don't want to have everything named And side note, I played around with generating MSL directly and it looked something like this, so that's the alternative to adding spirv-cross if we want to have a Metal renderer. It requires wrapping every constant buffer access in a macro, since MSL doesn't throw all constant buffer contents into the global namespace. |
Yup, thought of that but was thinking it'd be simpler as is. But maybe not. If this isn't merged soon, I will look into it, otherwise I'll do a separate PR.
Neat that you got that working! However, that macro heavy approach was actually what phire and I were hoping to avoid. We currently do that sort of thing for post-processing (and I had to do that even more in my rewrite) and it just makes for ugly code to read/write. But more importantly, if a user wants to write a custom shader, it means we have to expose all those details to them. I'd prefer not to do that. |
Yeah, considering the complexity it adds, I think continuing to unify around GLSL and using spirv-cross is the best approach. |
…3a2848e1a7da6d9755ca Co-authored-by: tellowkrinkle <tellowkrinkle@gmail.com>
Co-authored-by: tellowkrinkle <tellowkrinkle@gmail.com>
…tching the specialized shader
…o SPIRV generation
…g GLSL to SPIR-V with validation layers turned off
Considering we have some changes on the docket that will reduce stuttering by as much (or more?) than this costs, I think we can justify merging this. It also brings us closer to a metal backend, which will help our macOS users a lot. |
Fix CMake Windows build after #10673 (HLSL from SPIRV).
@JMC47 Sorry for necroing (I just read it) but are we talking "ideas" here or some actual PRs I could try out? Ever since I've switched to Linux I've been stuck with OpenGL for the stutter-free experience. For comparison, on my old setup with a much weaker CPU and Intel GPU, it looked like this (I haven't actually checked but I made some notes years ago):
But now, better CPU and Nvidia GPU:
I really think that the only way is to generate SPIR-V directly. Another emulator I can list which does that is Yuzu, which generates SPIR-V with Vulkan and lets you decide between SPIR-V and GLSL with OpenGL. Regarding the data, I know I'm talking about several hundreds of FPS here. But that's only the way I test. Playing at 3x and when there's a lot of movement going on, the difference between Vulkan and OpenGL can really be playable or not. |
This generates HLSL from SPIRV.*
There are a couple reasons this is worthwhile:
The second advantage was the main driver behind implementing this feature (to prepare for the pp rewrite).
Here's the task list:
* Unfortunately SPIRV-Cross only supports Vertex, Pixel, and Compute shaders. That means Geometry shaders still use HLSL. Luckily, there isn't much code there to support that path and there are no user written geometry shaders. But it does make things a little klunky in Dolphin code as one of the helper functions is used there and in the vertex/pixel shader so we have to handle it in a special manner.