Live data from Hacker News

Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

dolphin-emu.org

11–20 of 72 posts

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#11
post #5

Has it really been 9 years since I started working on Ubershaders? I'm a little surprised no better solution has come along. Vulkan didn't even exist back then (and DirectX 12 had only just released) but instead of making things better, it digs it's feet even deeper into the assumption that all shaders will be known ahead of time (resulting in long "shader recompilation" dialogs on startup on many games). I've been t…

Don't you think intermediate representation like SPIR-V would suffice in mostly eliminating stutter? Yuzu used that and shader stutter seemed to be minimal and I can image that the shaders generated by Yuzu are much more complex than Dolphin.

The only step that SPIR-V replaces is parsing the GLSL to an AST tree, and that's only a small part of the total time to compile a shader. Usually the bottleneck is Register allocation or scheduling.

Back when Vulkan was developed, there were a bunch of OpenGL drivers out there which had random AST parsing bugs (Dolphin even has a bunch of workarounds for them); So a large chunk of the motivation for SPIR-V was avoiding the need for every driver to implement their own GLSL parser and the associated bugs.

The problem for Dolphin is not the complexity of the shader, but the quantity.

Shaders in modern games are usually written manually (or authored in a shader node editor by an artist), so it's rare for a game to have more than a few thousand total. Better games might only have a few dozen for the entire game.

But because gamecube/Wii games configure the TEV pixel pipeline though a dynamic API, some games use that API in a pattern where Dolphin can find itself generating hundreds of shaders per second. Some games even manage to generate new shaders continually as you play, because they append junk state to their pixel pixeline state which dolphin doesn't detect as a duplicate.

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#12
post #7
post #4

The pixel shading of the GameCube were slower than that of the OG Xbox. But, it was quite a bit more flexible. Specifically, the GameCube could load a couple textures, do a bit of math, then use that math to load some more texels. The Xbox could only load textures as the starting instructions before doing math and tried to make up for that with a few "do very specific math and load textures in a single instruction" o…

> The Xbox could only load textures as the starting instructions before doing math and tried to make up for that with a few "do very specific math and load textures in a single instruction" ops. If you look closely, the TEV actually shares the same limitation, it's just that the traditional representation interleaves the texture fetch and math instructions (Because the 3rd texture fetch "instruction" always feeds int…

[deleted]

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#13
post #11

Earlier quoted context omitted.

Don't you think intermediate representation like SPIR-V would suffice in mostly eliminating stutter? Yuzu used that and shader stutter seemed to be minimal and I can image that the shaders generated by Yuzu are much more complex than Dolphin.

The only step that SPIR-V replaces is parsing the GLSL to an AST tree, and that's only a small part of the total time to compile a shader. Usually the bottleneck is Register allocation or scheduling. Back when Vulkan was developed, there were a bunch of OpenGL drivers out there which had random AST parsing bugs (Dolphin even has a bunch of workarounds for them); So a large chunk of the motivation for SPIR-V was avoid…

Shaving off the frontend costs is not going to be nothing. I don't know if Dolphin is still using FXC/D3DCompile or if they've switched to DXC, but FXC is infamously slow, even for very simple shaders. Dolphin's shaders are medium-complexity IIRC, so I'd expect removing the frontend to be a decent win.

The driver PSO compilers aren't amazing but they're also not terrible. Most games do some form of hash-n-cache for PSO compilation and while stutters are still an issue, it's not the worst in the world. With the frontend gone, I'd expect ~50 shaders per second to be roughly stutter-free.

Being smarter about specialization is probably a good idea -- having a blend between "GPU interpreter" and "full specialized pipeline" is where I think you should head. Several of the weirder TEV features could probably be moved to branching on dynamic buffer contents.

Not to mention using newer features like bindless to merge draw calls. I always wanted to do that but got too busy before I stopped working on Dolphin :)

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#14
Does anyone know why this isn't an issue for modern games on PC? I assume it's because more uniforms are used, and the amount of shaders that actually need to be compiled at runtime is minimized, not to mention that the Graphics API is optimized to compile the shaders in the format they are provided. So is the issue with Dolphin that GameCube games would compile new shaders for lots of different configurations of effects / stages? Would some sort of preprocessor that converts shader compilations to some mini-ubershader with uniforms that can handle a lot of the different effects be feasible? And then depending on how many completely different shaders there are you would have many different mini-ubershaders?

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#15
post #14

Does anyone know why this isn't an issue for modern games on PC? I assume it's because more uniforms are used, and the amount of shaders that actually need to be compiled at runtime is minimized, not to mention that the Graphics API is optimized to compile the shaders in the format they are provided. So is the issue with Dolphin that GameCube games would compile new shaders for lots of different configurations of eff…

I think it's because PC games know they need to deal with compilation, so they do it on the load screen or whatever. GC games can pre-compile them and just stuff it on the disk, so there's no compilation cost.

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#16
post #14

Does anyone know why this isn't an issue for modern games on PC? I assume it's because more uniforms are used, and the amount of shaders that actually need to be compiled at runtime is minimized, not to mention that the Graphics API is optimized to compile the shaders in the format they are provided. So is the issue with Dolphin that GameCube games would compile new shaders for lots of different configurations of eff…

It is an issue with some modern games (I recently played a title that had a "Preparing Shaders..." loading screen); the main difference is that those games know the full set of what they need to do and can precompile most of them up-front, while an emulator like Dolphin needs to handle whatever the game throws it on the fly.

Also, games might know what shaders it can skip and what it can't, but Dolphin can't skip shaders if they aren't compiled, because it doesn't know what the game will do with the render (e.g. Miis work by rendering their heads once into a texture, and then reusing that. If it skips the render because the shader isn't ready, the Mii will just be missing forever).

Some emulators handle this by sharing "shader caches" between users so that they have a better idea of what the game will use; Dolphin opted for a different solution here.

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#17
post #5

Has it really been 9 years since I started working on Ubershaders? I'm a little surprised no better solution has come along. Vulkan didn't even exist back then (and DirectX 12 had only just released) but instead of making things better, it digs it's feet even deeper into the assumption that all shaders will be known ahead of time (resulting in long "shader recompilation" dialogs on startup on many games). I've been t…

I still don’t understand why you didn’t use the precompiled shaders packed with the games… you’re emulating the GameCube or Wii GPU, and it’s never going to change, and the games provide precompiled shaders.

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#18
It's interesting to see the parallels between this and an engine for a dynamic programming language. The one I'm most familiar with is JavaScript.

When you first need to run something, you run it on the interpreter (JS) / ubershader (Dolphin). But once you know it's going to be run repeatedly (rarely for JS, almost always for Dolphin), you kick off an async compilation to produce JIT code (JS) / a specialized shader (Dolphin). You continue running in the expensive mode (interpreter / ubershader) until the compilation is complete, then you switch over seamlessly.

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#19
post #5

Has it really been 9 years since I started working on Ubershaders? I'm a little surprised no better solution has come along. Vulkan didn't even exist back then (and DirectX 12 had only just released) but instead of making things better, it digs it's feet even deeper into the assumption that all shaders will be known ahead of time (resulting in long "shader recompilation" dialogs on startup on many games). I've been t…

I still don’t understand why you didn’t use the precompiled shaders packed with the games… you’re emulating the GameCube or Wii GPU, and it’s never going to change, and the games provide precompiled shaders.

They're precompiled for the console GPU architecture, not the PC architecture, so they can't be used directly and still need to be emulated - I think those precompiled shaders are the input to the ubershader.

Re: Ubershaders: A Ridiculous Solution to an Impossible Problem (2017)

#20
post #5

Has it really been 9 years since I started working on Ubershaders? I'm a little surprised no better solution has come along. Vulkan didn't even exist back then (and DirectX 12 had only just released) but instead of making things better, it digs it's feet even deeper into the assumption that all shaders will be known ahead of time (resulting in long "shader recompilation" dialogs on startup on many games). I've been t…

I still don’t understand why you didn’t use the precompiled shaders packed with the games… you’re emulating the GameCube or Wii GPU, and it’s never going to change, and the games provide precompiled shaders.

Wait, I hought that's what the ubershaders are. What you say is what I kept thinking for much of the article - "just" emulate the GPU, no compiler needed. And then they did.
Post reply on HN