Hi, In the past days there was a bit of discussion about the implementation design of our future d3d10 implementation. The major question was wether we should make a clean start over with opengl 3.0, or extend wined3d for d3d10.
A few facts: *) D3D10 is a clean restart without any backwards compatiblity, so is gl3. The fixed function pipeline was removed in both.
*) The D3D10 interface is a present. Many of the nasty things in d3d9 have gone. SRGB textures are a pixel format property now. Sampler states are a texture property, not a device setting. Offscreen-rendering is more fbo like.
*) WineD3D contains a huge set of functionality of d3d10 already. D3D10 is an evolutionary step, not a revolution. I estimate that 80% of the functionality that is of our interest already existed in d3d9. Code reuse, especially of the shader code and texture management, is desireable.
*) GL3 isn't out yet. When will we have a gl3 implementation on all platforms and drivers?
*) If we split, we do not have to take care for old opengl implementations and missing extensions. For d3d10 we could just require gl3, period. Of course that will only work satisfiably for the user if there are gl3 implementations everywhere.
So we have two ways:
1) Do the same Microsoft did, and do a fresh start. Some code, like the shader code, could be copied over and forked. This is propably the fastest way, but it leaves us with 2 different d3d implementation. The d3d10 implementation on the other hand would be free of old junk. It would make it hard to run d3d10 on gl2+extensions, and even more harder to implement d3d9- on gl3.
2) Extend wined3d. We could use the inheritance scheme like in old ddraw, where the non-rendering functionality was implemented in a base object, and the renderer specific things(DGA / User / 3D) was implemented in objects derived from the base objects. This was a nice thing, but it made the code next to unreadable IMHO because of a huge number of objects and unintuitive interactions(DGA code calling User stuff, common code calling callbacks that are set in 5 places in the code, 5 different surface types).
WineD3D already has the attachment points for such an abstraction. We have COM vtables and state management callbacks. Implementing d3d10 properly in wined3d is most likely more work than a restart is, but it would allow us to reuse some code. What we would have to do is this:
*) Make sampler states work like in opengl. D3D7-9 takes care for updating the per texture states based on the device states. This will require some code to be moved from wined3d to d3d7-9 and duplicated in the 3 libs, most notable sampler state tracking in stateblocks.
*) Move the srgb flag -> format matching from wined3d to d3d9. Before this can be done, wined3d has to be changed from D3DFORMAT to DXGI_FORMAT style.
*) Clearly separate gl-specific code from non-gl-specific code in surface, texture, cubetexture, volumetexture, indexbuffer and vertexbuffer. Then split them in a base object and a derived gl2 object. Add a gl3 object implementing the gl-specific stuff in gl3. Make sure there is no gl specific buffer/texture stuff in the device(like CreateVBO &
*) Add a 2nd state table and callback functions for gl3. GL3 will have different state linkings. Most of the states can stay unimplemented unless we want to run d3d9 with gl3. D3D10 is much simpler here because the fixed function pipeline was removed.
*) Do something about the context manager. Multithreading has changed in d3d10, and it may change in gl3. Offscreen rendering in d3d10 can require fbos(no point in d3d10 offscreen rendering without them), this has much less hassles than the back buffer or pbuffer orm. Context management will most likely be much simpler in d3d10+gl3.
Andras tells me that he has the d3d10 stubs(no rendering yet) done now, and he is writing some tests currently, then he will send stubs and tests in.
Which way do you think should we go?
For the most part that nicely sums up the problem :-). One consideration that I think should be added to that list is that we probably want to be able to run at least d3d8 and d3d9, and possibly ddraw, on top of GL 3.
The decision on what to do for a big part depends on what OpenGL 3.0 actually is. From carefully reading the latest OpenGL 3.0 announcements and their forums I come to the conclusion which I'll explain below.
There are basically two new OpenGL versions named respectively: Longs Peak, and Mt. Evans. Longs Peak is a cleaned up version of OpenGL 2.x and Mt. Evans would add DX10 features. For a long time everyone expected Mt. Evans to become OpenGL 3.0 and Longs Peak to be some OpenGL 2.x version.
Recently Longs Peak has been announced as OpenGL 3.0. Due to time constraints they weren't able to add all the features they wanted to Longs Peak, so they have added Longs Peak Reloaded (OpenGL 3.1?) which will arrive 2-3 months after 3.0. Further the 'DX10' version 'Mt. Evans' will arrive 3-5 months after 3.0.
So it appears like OpenGL 3.0 is going to be a port of OpenGL 2.0 to the new object framework. All the sources mention that all fixed function stuff that can be done using shaders has also been removed. Further according to posts in the OpenGL 3.0 topic at opengl.org some stuff has been kept using integers because of backwards compatibility.
What does this mean for Wine? Well it seems like OpenGL 2.1 hardware like the Geforce6/7 can perfectly work using OpenGL 3.0. For DX10 functionality you ofcourse need extensions. Further it might mean that none of the DX10 opengl functionality will be ported back to OpenGL 2.x. Nvidia has done it but I'm not sure if ATI and others will follow. I expect them to add those extensions only to their 3.0 drivers. (Remember that ATI is working on a new codebase for their OpenGL drivers. This might be the real reason ..)
Roderick
What it comes down to is that there are two things we have to make a decision about: - Do we want to support GL3 in the existing wined3d? - Do we want to support D3D10 on top of the existing wined3d?
I've got a slight preference towards at least trying to support both with the same wined3d, mostly for maintainability reasons. Iow, I think it will be a major pain if we have to fix bugs in 2 or 3 copies of the same code.
On Saturday 18 August 2007 13:59, H. Verbeet wrote:
What it comes down to is that there are two things we have to make a decision about:
- Do we want to support GL3 in the existing wined3d?
- Do we want to support D3D10 on top of the existing wined3d?
I've got a slight preference towards at least trying to support both with the same wined3d, mostly for maintainability reasons. Iow, I think it will be a major pain if we have to fix bugs in 2 or 3 copies of the same code.
From what I have seen GL3 is very different. It would be like maintaining a GTK and a QT backend in one library. They use very different calls (glBegin/glEnable and so are gone), need different WGL contexts and so on.
Sure in case of a wined3d-gl3 you'll end up fixing bugs twice. But for quite a number of bugs you'll need to patch both gl2 and gl3 anyway.
Second what do you guys things of regressions? We really should keep ddraw/d3d7/d3d8/d3d9 stable. Else it will take another 3 months before it is in a decent shape again.
My suggestion would be to create a new wined3d with the same interface as the current wined3d. If needed ddraw/d3d8/d3d9 can use this wined3d too. Personally I would add d3d9ex.dll like on Vista which can use wined3d-gl3.
Roderick
On 18/08/07, Roderick Colenbrander thunderbird2k@gmx.net wrote:
From what I have seen GL3 is very different. It would be like maintaining a GTK and a QT backend in one library. They use very different calls (glBegin/glEnable and so are gone), need different WGL contexts and so on.
Sure in case of a wined3d-gl3 you'll end up fixing bugs twice. But for quite a number of bugs you'll need to patch both gl2 and gl3 anyway.
That's true, but there's also a rather large part of wined3d that's not GL specific in the first place. The most obvious examples are most of the shader stuff and state management, but that's certainly not all.
Second what do you guys things of regressions? We really should keep ddraw/d3d7/d3d8/d3d9 stable. Else it will take another 3 months before it is in a decent shape again.
I don't think it'll be much worse then what we're doing at the moment... (yeah, I'm bisecting another regression at the moment).
My suggestion would be to create a new wined3d with the same interface as the current wined3d. If needed ddraw/d3d8/d3d9 can use this wined3d too. Personally I would add d3d9ex.dll like on Vista which can use wined3d-gl3.
I certainly wouldn't discard that option either. Keeping things together, if possible, is just a slight preference. As for d3d9ex, it appears to mostly be d3d9 with some extra flags in a couple of places. I've got no idea if anyone is actually using it, or will be, but it shouldn't be particularly hard to add.
Am Samstag, 18. August 2007 14:34 schrieb H. Verbeet:
My suggestion would be to create a new wined3d with the same interface as the current wined3d. If needed ddraw/d3d8/d3d9 can use this wined3d too. Personally I would add d3d9ex.dll like on Vista which can use wined3d-gl3.
I certainly wouldn't discard that option either. Keeping things together, if possible, is just a slight preference. As for d3d9ex, it appears to mostly be d3d9 with some extra flags in a couple of places. I've got no idea if anyone is actually using it, or will be, but it shouldn't be particularly hard to add.
I am opposed to writing a 2nd wined3d with the same interface. One of the main problems, if we stay with one wined3d, is to map the d3d9 and d3d10 interface together efficiently(remember: Microsoft went for a new low level interface). If we use 2 wined3d's with the same interface we do not gain much compared to a common codebase(still two different implementations), but we still have the hassle of designing an internal interface that can run both d3d versions and is suitable for gl3 and very old gl 1.2 versions.
H. Verbeet wrote:
On 18/08/07, Roderick Colenbrander thunderbird2k@gmx.net wrote:
From what I have seen GL3 is very different. It would be like maintaining a GTK and a QT backend in one library. They use very different calls (glBegin/glEnable and so are gone), need different WGL contexts and so on.
Sure in case of a wined3d-gl3 you'll end up fixing bugs twice. But for quite a number of bugs you'll need to patch both gl2 and gl3 anyway.
That's true, but there's also a rather large part of wined3d that's not GL specific in the first place. The most obvious examples are most of the shader stuff and state management, but that's certainly not all.
The shader stuff uses two different backends and an intermediate interface (SHADER_OPCODE_ARG) to isolate the asm parser. Other parts of wined3d could do the same thing - you are interface constrained from the top (d3d) and from the bottom (gl), so it makes sense to focus on intermediate representations of the data. If it's hard to replace your GL backend, then the code isn't properly structured.
It's interesting that all this work was done to move towards convergence: D3D1-9 -> Wined3d Pixelshaders, Vertexshader -> shared backend GLSL, ARB -> single shader parser
...and splitting things up is being considered yet again. I'm not sure I like the idea of throwing away working code to start "fresh" - but I'm no longer writing d3d code, so :)
Am Samstag, 18. August 2007 19:59 schrieb Ivan Gyurdiev:
The shader stuff uses two different backends and an intermediate interface (SHADER_OPCODE_ARG) to isolate the asm parser. Other parts of wined3d could do the same thing - you are interface constrained from the top (d3d) and from the bottom (gl), so it makes sense to focus on intermediate representations of the data. If it's hard to replace your GL backend, then the code isn't properly structured.
...and splitting things up is being considered yet again. I'm not sure I like the idea of throwing away working code to start "fresh" - but I'm no longer writing d3d code, so :)
No question it is possible to keep things merged, but keep in mind that d3d10 throws away some things that are a major thing the current d3d->gl wrapping code is dealing with, like having sampler states device global. The step from d3d9 -> d3d10 is much bigger interface wise than d3d7(*) -> d3d8 or d3d8 -> d3d9 have been, it is so big that Microsoft decided to throw away their internal implementation and start over. This is why we discuss this. If Microsoft hadn't entirely changed the way d3d works internally there wouldn't be any reason for us to do the same too.
D3D10 is a present. It is much closer to opengl than to d3d9. Having a common code means to deal with the overhead of mapping d3d9 to opengl in code that also runs d3d10. The question is how to deal with that overhead.
(*) d3d7->d3d8 was a huge change too because it got rid of the ddraw stuff in d3d. However, the differences are initialization-wise only, rendering once the device is there works the same way in d3d7. d3d10 has a different "run-time" interface.
For what it's worth, although the idea of not starting with a clean state has its advantages (not in the least being able to support D3D10 software in a short time frame) I think that the clean slate argument wins out for me overall.
Yes, it's more work in the short term, but I can't help thinking of a situation down the line where something gets done with the D3D10 framework - some as yet unknown extension or iteration to D3D11 or whatever - that took the library down a path that code based on Wine's current implementation couldn't follow, necessitating a restart from scratch later on anyway.
Worst case scenario, perhaps, but a painful one that's probably worth thinking about. It'd be a shame if it did happen that way and D3D10 compatibility went backwards while it got restarted, plus there'd be a load of D3D10 cruft in the D3D9 library that would need to get culled...
-- Chris