Am Freitag, 11. April 2008 22:42:17 schrieb H. Verbeet:
I did not yet read it in depth, so I am just replying to a few concerns I spotted. I'll look at it more in-depth tomorrow.
- The state table should be selectable based on the available opengl
features and possibly registry settings. I think we all agree on that
Up to the level of being able to use different state handlers in different situations. I don't necessarily agree with copying and swapping the entire table in one piece.
Agreed, we just want to be able to swap states, in which way is open.
- We want a fixed function vertex and fragment pipeline replacement
with ARB and GLSL
Only GLSL is a requirement for me. ARB could be nice, but is probably redundant.
Intel cards? Also GLSL has the problem with the link times.
- A nice to have is to be able to use the replacement pipelines
together with shaders, but that is not a hard requirement for me. We need an ARB and GLSL replacement anyway.
I assume you mean atifs & nvrc specifically here, in which case this is probably a bit more important than "nice to have". The most tricky situation to support here will be cards that support vertex shaders, but not fragment shaders. If we want to support pixel shaders using atifs / nvrc we have to allow mixing GLSL / ARB with nvrc / atifs for it to be of any use.
The current implementation allows that, we're using ATIFS+ARBVP
Aside from being clearer this allows you to swap these parts out independently from each other and possibly skip applying them as a whole in case a shader is active for that part of the pipeline (I imagine this could have some performance advantages as well, although I'm not sure how much).
For the performance, it depends on the app. If we skip applying (redundant) fixed function settings when a shader is used, we have to reapply all of them the shader use might have changed when the shader is deactivated. It's a decision between making shader on-off switches cheap vs filtering out redundant state changes done by the app. Currently there is no additional fixed function pipeline cost involved when using shaders as long as the app doesn't touch the ffp states.
struct IWineD3DDeviceImpl { ... struct state_management_t vertex_state_manager; struct state_management_t fragment_state_manager; struct state_management_t other_state_manager; struct shader_backend_t shader_backend;
void *vertex_private_data; void *fragment_private_data; void *other_private_data; void *shader_private_data; ...
};
One of the reasons for using a single state table was that we have interconnections between the vertex states, fragment states and other states. For example, where would you put the vertex buffer loading? Is that an "other" state, or a vertex state? The FVF and the vertex shader influence if we're entering the FF or shader vertex processing codepaths. The FVF affects fogging, which is a vertex state in some shader implementations(nvts, atifs), but implemented in pixel shaders in GLSL and ARB. The texture transform flags are a fixed function vertex state on paper, but we have to compile the D3DTTFF_PROJECTED flag into the fragment shader. (we already do so, that's documented on the msdn, so clearly a missdesign on Microsoft's side). There are many more examples of vertex-fragment-other state interconnections.
This doesn't support mixing eg. ARB vertex shaders with NVRC pixel shaders, but it would "simply" be a matter of splitting up the shader backend in a similar way to the state table. Important to note here is that the private data could be shared between fixed function replacements and the shader backend, like in the case of GLSL. I could imagine using a structure more similar to state_management_t for the shader backend as well.
The unsplit shader backend is the current d3d shader implementation + Ivan's pipeline linker object. If you split them up, where do you set GLSL shader constants?
Also note that the GLSL pixel shaders depend on the type of vertex processing(non-GLSL or GLSL) to load the 3.0 varyings correctly. We could get rid of that by requiring GLSL vp, but that would break requirement 4, using the GL fixed function pipeline.
My concern is that if you split vertex processing and fragment processing up, you need a linker object that deals with linking. This linker object has know about the vertex and fragment processing state handlers and tables, thus creating a special linker for each vs-ps-vff-ffp-other combination. I don't have any objections against that in principle, but I am afraid that due to the high interconnection between vertex, fragment and other states we would end up with implementing most things in the linker.