Am Donnerstag, 20. März 2008 05:51:23 schrieb Ivan Gyurdiev:
It looks to me as if shader_backend is being overloaded for many different purposes that are not really related to each other. Typical object structure is to group related data an functions in one place, but what's happening in shader_backend is that it has no data of its own, and it's a vtable routing between different GL extensions with the data being scattered across multiple different places.
Yes, you're right, the shader backend does a few things right now. You have to see it as something dealing with OpenGL settings, don't see it as something talking D3D slang. Maybe renaming it to gl_pipeline_backend would give it a more suitable name.
I think it would be worthwhile to review all of this, and see if this organization makes sense. Why aren't the functions grouped together with the data ? Why is some of the data in the device object ? Why are functions managing different data containers in the same vtable ?
Henri once suggested making the shader_backend_t structure a COM object, that is created and destroyed by the device. That would make the state of the data it manages clearer(belongs to the shader object), though it would add some stuff we don't need, like the IUnknown parts, refcounting. If we did that we could call the "shader function routing" "inheritance" and are well within OOP slang again.
Keep in mind though that a D3DDevice is a conglomerate of many different things(fixed function, shaders, evaluators, resource management, ...), and many of the critiques you mentioned apply to the D3D API as a whole. And even if our shader_backend_t is opengl-centric, we can't fully ignore the D3D design.
I am no longer familiar with the details, but there's way too many things called "shader" by now - d3d shader, gl shader, this made up "shader_backend" that actually does fixed function stuff and represents neither. Maybe it makes sense to create new object types - like a 'pipeline', containing a 'vertex processor', 'fragment processor' (not necessarily implemented via shaders). Maybe each of these should have a "fixed" and "dynamic" facing d3d API, but attach or detach to the pipeline in the same way. Maybe they can have different gl extensions "backend" implementing each.
My concern is that if we break up the shader structure into multiple objects(e.g. vertex shader handler, pixel shader handler, fixed function vertex replacement, fixed function pipeline replacement, depth blit handler, pipeline linker), then we'll get simple single objects, but the putting these parts together adds more complexity than we save in the first place. Often in OOP programs(and other paradigms as well) you don't know what one component does without knowing the whole program.