Game-side graphics code here in HLSL.
When I started coding shaders there was an implicit assumption that people who weren’t hardcore graphics programmers would be very bad at making performant shaders. So I, like many others, did the whole prototype-and-pass-off thing. In practice, this meant waiting on another programmer to do work they didn’t enjoy. All the fun stuff was finished, it was the CPU-side setup and optimization that was left. I was unhappy that I had to wait to see my results in-game, the artists were unhappy that they were waiting on new tech to start content work, and the graphics programmers were unhappy to get stuck with the short end of the stick. Sounds ideal, eh?
About a year after I joined Valve, the programmer I was working with at the time said, heck with this, and walked me through the setup code. The idea was that it would be better to at see it in game as soon as possible. Then we could evaluate and test perf. I wasn’t even going to check in, just run some experiments. What ended up happening is that I got mentored through the process, and after that people just stopped checking my code because it wasn’t horrible! I’m not the only one who has had this experience. … Paging Heidi…?! Sometimes making assumptions about what’s going to create a problem is the worst problem you have. It stops you from trying things that might turn out to be big successes.
You actually have to work pretty hard to make a really badly performing shader on modern hardware. (OK, you don’t, but it’s hard to do it by accident.) After a little bit of experience, common sense kicks in, like “oh! I should not create a huge chain of non-contiguous dependent texture reads!” Most of the time things artists are asking for aren’t really that expensive, they’re just different than what’s available. And – shocker – most shaders don’t have to be ideally performant to be shippable. You’d expect we’d spend tons of time profiling and perfecting every shader, but the opportunity cost for that is too high. If the game is already performant, saving one instruction isn’t going to make the game perceptably better for your customers. But the time you waste tracking down those minor problems might mean something else important doesn’t make it in – something that your customers might really care about.
I check in shaders with the expectation that, somewhere down the line, I’ll have to write simpler fallbacks for lower-end hardware, or fix some memory or performance issues. Once we’re happy with the look of the shader we start caring about that sort of thing. Get it working first, get it working fast second. So long as it doesn’t block development that’s usually fine. Sometimes a graphics programmer will come to me because I’ve created a problem, but we just work through it and fix it. The building somehow doesn’t collapse. At times I need help, but mostly I’m able to solve it on my own once the problem has been identified. It saves everyone time and lets us each focus on our own tasks. And it’s easier for me to cut features and bugfix than for someone else because, hey, I know what it’s supposed to look like. Efficiency!