Emanuele wrote:Hi blu, do you mind if I ask you if the "codegen -> compile -> link" bit is an educated guess or you have some inside information? I would hope that 1.1 drivers could just stitch and patch some pre-written code blocks together.
Hi Emanuele. Yes, stitching & patching pre-existing blocks of code is normally how codegen is done in ES1.1 drivers. Apologies if the word 'codegen' sounds too abstract or pretentious.
Matching the current rendering state (I mean at enable/disable level) against
a few cached versions of the shaders looks also feasible. I have no inside information, but that is what I would do.
Well, part of the problem is that you need to produce one all-encompassing shader (of vertex + fragment parts) that covers the entire state, a 'ubershader' of the fixed pipeline state. Now, keeping just 'a few' cached versions of that could be tricky. I mean, you should definitely keep the top MRU one, but other than that, things might become statistically tough. Consider a rudimentary scenario based on confining light contributors, where each draw ends up with its own set of lights Li .. Lj enabled, where {Li, .., Lj} is an arbitrary non-empty subset of the pipeline's complete light set.
Even though the difference in the shaders might look utterly minimal at first glance - just different indexation in some structures or masking/unmasking different results, you may actually want to produce a new shader each and every time if you want to retain efficiency, i.e. avoid a control statement inside the shading loop of the vertex shader, potentially masking computationally-costly results and effectively wasting the engine's optimisation logic which worked hard picking relevant lights. So caching a few already-done shaders does not hurt here, but what benefits that'd provide would depend on the upper-level engine logic that decides which lights to use each draw. Actually, whether you might want to re-codegen/build your ubershader, versus paying the cost up front of any unwanted light contributors in your vertex shader, might be a decision which should be best considered with the knowledge of how big the vertex buffer for the draw is - for small-enough vertex buffers it could be cumulatively faster to re-use a more-inefficient vertex shader but avoid the codegen/build phase, which could end up more costly.
It's just a trivial example, but it illustrates the bane of ES1 - it has to be all sorts of 'smart' and perhaps apply various heuristics if it wants to be efficient - something which ES2 leaves to the right decision maker - the caller. In this regard, ES2 API is the better abstraction for the task of sending graphic primitives down to a contemporary GPU, whereas ES1 exists for legacy reasons alone. That does not mean you should never consider using ES1 for a new project running on ES2 hw, but it is a good enough counter-argument for most such cases.