Hacker News new | ask | show | jobs
by conorpo 765 days ago
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?
6 comments

The programmer of a modern PC game knows that they will be using shaders, and can arrange for them all to be compiled and sent to the GPU during a loading screen. That eliminates the lag, because there is no delay when choosing which shader to use for the next triangle. On the other hand it makes the loading screen take longer.

Meanwhile the programmer of a console game, not using shaders, could set GPU registers to any configuration they wanted just before rendering the next triangle. You have to actually play the game to find out what configurations it programs into the GPU, because those configurations are not neatly organized into a set of discrete shaders. Even then there is no guarantee that you found all possible configurations used by the game. The videos in the article provide a good example: the player fires a gun with luminous bullets, so on that frame the walls and floors need to be rendered with an extra light source. That requires reconfiguring the GPU to take that light source into account, then changing the configuration to render the weapon itself, then changing it again to render the HUD, and so on.

Now imagine that you go to a place on a different level where the walls are not shiny, and it doesn't bother to render the walls with the extra light source. Or it renders them with extra vertex lighting but not extra specular lighting. Now combine that with every type of wall and floor in the game; they might all need a unique shader to be lit correctly by that one gun. To find all possible GPU configurations you need to fire that gun, and every other, near every single different type of wall and floor texture used in the game. And there are a dozen different guns.

And then you need to do it all again while wearing the night–vision goggles, because that causes everything to be rendered with a different configuration yet again.

Every one of those unique combinations needs to be made into a shader, and there’s just no way to be sure that you have actually collected all of them. Or you can write a single Ubershader that can, by using branches, loops, and other advanced tricks, emulate the entire capabilities of the emulated GPU. Then you can program the Ubershader by sending all of the emulated GPUs register values as uniforms.

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.

It’s not a problem for the PS/Xbox/Switch. They have known hardware and it can all be recompiled.

But from what I’ve heard it’s often still an issue on PCs (I’m a Mac guy). I’ve seen videos of shader compilation stutters, even in games with a precompilation step that’s supposed to avoid that.

Digital Foundry has covered this many times. The link in a sibling comment to them on Eurogamer is a great place to start.

Steam works around this by letting users enable shader precompilation in settings. If you want a console-like experience (eg. like Steam Deck) and you don't care so much about storage space, you can toggle it on and eliminate the stutter before booting up. Most people leave this off, which really ruins the experience on shader-heavy engines like UE4.

This is generally an everyone problem, though. If gaming on Mac was caught-up with where Linux is today, there would probably be a few precompilation steps there too. If you wanted to play Fallout 3 on your Android/iPhone device, it's the same story.

I’ve heard that helps a lot but I know new driver versions/etc can trigger a recompile. And the less common your setup the less likely it’s an issue.

I don’t think it’s an issue on Apple Silicon Macs(not sure) because like the iPhone there is a very tiny list of variables so precompiling is easy.

It is an issue for some modern big titles on PC. Trying to find some links that have somewhat general overview ...

https://twistedvoxel.com/unreal-engine-5-pc-stuttering-issue...

https://www.eurogamer.net/digitalfoundry-2022-df-direct-week...

This a big issue in modern PC games, games that don’t do a shader pre compile before starting the game suffer from serious shader compile stutters while playing the 1st time, dropping frames every time a new variation is required for a particular frame, it’s actually bad.
gcn games never anticipated shader compilation time because it didn't exist.

shaders weren't a thing when the gcn released. it may be arguable, but nobody even used the word at the time. shader compilation time is an issue for modern games on the PC, and because of this, developers anticipate and work around it.

on the gcn, specialized fixed-function pipelines were available, and could be composed by some limited configuration (literally, 24 instructions). you may think of this as a sort of proto-shader, but significantly, the fixed-function pipelines embody quite a lot of behavior in specialized and limited hardware that is now typically achieved in software on more versatile hardware.

so, to replicate that specialized hardware, modern graphics hardware (which exposes its greater capability as simple computational primitives) must compile a shader program and run it. but on gcn, the tiny configuration of static hardware loads near-instantly.

Shaders as concept exists since 1980's,

https://en.m.wikipedia.org/wiki/TMS34010

https://en.m.wikipedia.org/wiki/RenderMan_Shading_Language

Just two examples, SIGGRAPH has plenty of paper on the subject.

A 2002 postmortem on the tech of Rogue Leader, a Gamecube launch title, already using the term "shaders":

https://www.gamedeveloper.com/programming/shader-integration...

The first video card with a programmable pixel shader was the Nvidia GeForce 3 (NV20), released in 2001. [1]

1: https://www.techpowerup.com/gpu-specs/nvidia-nv20.g644

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.
GC shaders are loosely based on GLSL, and OpenGL compilation model, even though GX(2) isn't OpenGL.
No, GameCube's TEVs have nothing to do with GLSL. The reference to GX2 implies you're confusing it with Wii U, inexplicably.
Yes I mixed them with Wii and Wii U,no need for "inexplicably" remark.