Hi, In the last days I've been working on using the OpenGL vertex buffer objects extension for IWineD3DVertexBuffer. The aims of this were:
* Store geometry data in the hardware for more efficient rendering * Convert the colors and rhw values on upload and get rid of drawStridedSlow
The result is in this diff, and it basically works, although not as good as I've hoped. It gives a nice performance boost to Battlefield 1942, and is an improvement for Half-Life 2, but it is not perfect yet. The main shortcomings are:
* Shader support: I'm afraid that the conversion code at this points breaks shaders. I've tested with battlefield 1942. The vertex shaders in this game don't work correctly yet, the hands of soldiers are missing and there are some incorrect planes with odd colors. However, with this patch the hands are drawn as apparently random vertices all over the screen. I think I'll need a little help from the shader people for that.
* The vertex conversion is slow, and it turned out that if the app Locks the Buffer every frame then drawStridedSlow is faster Converting + drawStridedSlow. Because of that VBOs and the conversion aren't used for vertex buffers in system memory and vbs with WINED3DUSAGE_DYNAMIC are not loaded into a vbo.
* In Direct3D7 there is no way for the app to specify a range of vertices to be locked. Because of that DX7 apps are generally slower if they update the vertices regularily. To avoid that drawback there is no VBO created for DX7 apps if they have vertex data that needs conversion. The geometry in DX7 apps is usually quite simple, so DrawStridedSlow isn't a big performance hit in those apps.
Stefan
On 6/9/06, Stefan Dösinger stefan@codeweavers.com wrote:
- Shader support: I'm afraid that the conversion code at this points breaks
shaders. I've tested with battlefield 1942. The vertex shaders in this game don't work correctly yet, the hands of soldiers are missing and there are some incorrect planes with odd colors. However, with this patch the hands are drawn as apparently random vertices all over the screen. I think I'll need a little help from the shader people for that.
I've been trying to figure out what is wrong with the shaders with SW Battlefront. They work fine in the menus when you first load the game, but once you start a match, they seem to break. It is quite visible with the loading text seen in these two screenshots I've taken (ignore the other parts, I had windows over top): ftp://resnet.dnip.net/ This is same text problem as in Battlefield 1942. The crosshair in battlefront is also messed up, as certain skybox textures. It has to do something with blending as well.
Jesse
Hi, This is an updated version of the VBO patch. The main difference is the integration with IWineD3DDevice::ProcessVertices which gives a nice performance boost for Half-Life 1 and propably Anarchy Online(not tested yet).
What is missing is work with vertex shaders(awaiting the download of the dx8 sdk for the dolphin demo) and an implementation of IDirect3DVertexbuffer7::ProcessVertices.
Cheers, Stefan
On Monday 12 June 2006 13:40, Stefan Dösinger wrote:
Hi,
This is an updated version of the VBO patch. The main difference is the integration with IWineD3DDevice::ProcessVertices which gives a nice performance boost for Half-Life 1 and propably Anarchy Online(not tested yet).
It will be better to move VBO creation and binding on vertexbuffer.c. (its why GetMemory didn't provide VBO id before, no need for that) Have you planned to use ti for index buffers too ?
What is missing is work with vertex shaders(awaiting the download of the dx8 sdk for the dolphin demo) and an implementation of IDirect3DVertexbuffer7::ProcessVertices.
The vertex conversion is slow, and it turned out that if the app Locks the Buffer every frame then drawStridedSlow is faster Converting + drawStridedSlow. Because of that VBOs and the conversion aren't used for vertex buffers in system memory and vbs with WINED3DUSAGE_DYNAMIC are not loaded into a vbo.
For that problem i had a prototype who remembered too many lock (in small times) and active the no-VBO flag :)
Cheers, Stefan
It will be better to move VBO creation and binding on vertexbuffer.c. (its why GetMemory didn't provide VBO id before, no need for that) Have you planned to use ti for index buffers too ?
That was my first idea(just bind the vertex buffer in GetMemory and return the offset), but the problem is that dx apps may split vertices on multiple buffers. They may store the position in buffer 1 and the colors of vertices in buffer 2. GetMemory is called when the FVF or declaration is converted into strided data. The strided data contains pointers to the vertex data which may come from many different VBs. I have to bind the VBO the data is stored in when I pass the data pointer to gl in LoadVertexArrays. This is perfectly ok for GL(and not a performance issue), but I need the VBO number in the strided data to know where each data comes from.
The vertex conversion is slow, and it turned out that if the app Locks the Buffer every frame then drawStridedSlow is faster Converting + drawStridedSlow. Because of that VBOs and the conversion aren't used for vertex buffers in system memory and vbs with WINED3DUSAGE_DYNAMIC are not loaded into a vbo.
For that problem i had a prototype who remembered too many lock (in small times) and active the no-VBO flag :)
I considered the same thing, considering that the app may be bad-behaved and set bad flags. Remembering the application's behavior seemed to be better.
However, I noticed that even well behaved apps(e.g. battlefield 1942) don't keep all the geometry they use in a map in vertex buffers at all time. Instead they load the area around the player, and load new stuff and throw away the old while the player moves through the map. As a result wined3d gets a bunch of IWineD3DVertexBuffer::Lock calls sporadically. Depending on the behavior of the player that is different. E.g. if a sniper stays at one place all the time there isn't much reload, but if he's flying a plane there is constantly new data. I couldn't think of any good heurisitics which could detect all that stuff, so I decided to rely on the flags set by the app. After all, the application developers know best what happens, and D3D8 and D3D9 apps are quite well-behaved compared to DDraw / D3D7 apps.
(Even if we can find a good way to handle the bf1942 and hl2 cases perfectly, who can say if we won't find a game which does something perfectly valid and fools our algorithms)
The same problem applies to textures and render targets, btw. For textures it can be solved quite well, render targes are more tricky.
Stefan