Hello, I've got some real rending working with d3d7 and wined3d: The Empire Earth intro movie is playing. Well, it's only a 2D bitblt thing, but anyway.
It's terribly slow on my ATI radeon M9, some GL calls take a lot of time, but it looks correct. A screenshot can be found at ftp://doesi.gmxhome.de/ee-movie.png.
Stefan
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hello, I've got some real rending working with d3d7 and wined3d: The Empire Earth intro movie is playing. Well, it's only a 2D bitblt thing, but anyway.
Great, keep up the good work..
It's terribly slow on my ATI radeon M9, some GL calls take a lot of time, but it looks correct. A screenshot can be found at ftp://doesi.gmxhome.de/ee-movie.png.
I've got a hack that should make those kind of blits faster. http://www.winehq.org/pipermail/wine-patches/2005-September/020829.html Oliver.
Stefan
___________________________________________________________ To help you stay safe and secure online, we've developed the all new Yahoo! Security Centre. http://uk.security.yahoo.com
Hello,
I've got a hack that should make those kind of blits faster. http://www.winehq.org/pipermail/wine-patches/2005-September/020829.html
I always thought this patch was commited to CVS. Must have been mistaken.
Stefan
On Thu, Oct 13, 2005 at 07:31:09PM +0200, Stefan Dösinger wrote:
I always thought this patch was commited to CVS. Must have been mistaken.
Well, will see if doing a patch like that could help in the DirectX code waiting for merging the DDraw and WineD3D code.
No idea if any application would actually be really accelerated though.
Lionel
Hello,
No idea if any application would actually be really accelerated though.
Well, it didn't help Empire Earth, it broke the intro video(black screen, not faster), but it showed me a bug in my code.
Stefan
Hello, I have come across a D3D7 call where I need some help with: IDirect3DDevice::DrawIndexedPrimitiveVB. The prototype is DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface, D3DPRIMITIVETYPE d3dptPrimitiveType, LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf, DWORD dwStartVertex, DWORD dwNumVertices, LPWORD lpwIndices, DWORD dwIndexCount, DWORD dwFlags)
I can't find any usable information about it on MSDN, and there's no equivalent in other D3D versions and WineD3D.
Is there an easy translation to IWineD3DDevice::DrawIndexedPrimitive orIWineD3DDevice::DrawIndexedPrimitiveUP, or do I have to add this call to WineD3D(based on the old implementation in D3D7 perhaps?).
Two other problems I am facing at the moment are a DIB crash in ddraw(also seen in the original D3D7 implementation) and a crash in the OpenGL libs with both fglrx and nvidia. Has anyone seen such GL crashes too? The crash dump is:
First chance exception: page fault on read access to 0x00039240 in 32-bit code (0x7e7fee5f). In 32 bit mode. fixme:dbghelp:elf_load_debug_info_from_map Alpha-support for Dwarf2 information for atiogl_a_dri.so Register dump: CS:0073 SS:007b DS:007b ES:007b FS:003b GS:0033 EIP:7e7fee5f ESP:5bc0f014 EBP:5bc0f16c EFLAGS:00210202( - 00 - -RI1) EAX:00000000 EBX:00000000 ECX:00000001 EDX:0000011c ESI:00000000 EDI:00000300 Stack dump: 0x5bc0f014: 7c228800 00000000 5bc0f0bc 7e88e588 0x5bc0f024: 7c228800 5aaa5380 5bc0f03c 00000001 0x5bc0f034: 00000004 00000000 00000000 00000000 0x5bc0f044: 7c228800 00000003 5bc0f09c 00228800 0x5bc0f054: 5aaa5300 5aaa54f8 5bc0f07c 7c228800 0x5bc0f064: 00000000 7c228800 5bc0f08c 7e87d07e Backtrace: =>1 0x7e7fee5f in atiogl_a_dri.so (+0x2cde5f) (0x5bc0f16c) 2 0x7e7fefb0 in atiogl_a_dri.so (+0x2cdfb0) (0x5bc0f2cc) 3 0x7dc2d182 IWineD3DSurfaceImpl_LockRect+0xad2(iface=0x790eaf48, pLockedRect=0x5bc0f374, pRect=0x0, Flags=0x0) [/wine/wine/dlls/wined3d/surface.c:561] in wined3d (0x5bc0f33c) 4 0x7dcc365d Main_DirectDrawSurface_Lock+0x40d(iface=0x7fe55570, prect=0x0, pDDSD=0x5bc0f3a8, flags=0x0, h=0x0) [/wine/wine/dlls/ddraw/surface_main.c:1155] in ddraw (0x5bc0f388) 5 0x7dcc2893 Main_DirectDrawSurface_GetDC+0x73(iface=0x7fe55570, phDC=0x5c308154) [/wine/wine/dlls/ddraw/surface_main.c:926] in ddraw (0x5bc0f434) fixme:dbghelp:sffip_cb NIY on 'C:\SSSI Development\Low-Level Engine\Graphics Engine\DX7 Display Plug-ins\DX7HRDisplay\Release\DX7HRDisplay.pdb' 6 0x7dcee4a7 ?DetachSurface@DX7Surface@@UAEJK@Z+0x210 in dx7hrdisplay (0x5bc0f488) fixme:dbghelp:sffip_cb NIY on 'C:\SSSI Development\Low-Level Engine\Main\Release\Low-Level Engine.pdb' 7 0x7fa6d17e ?DrawBackground@UIForm@@MAEJABVGERectangle@@@Z+0x76f in low-level engine (0x5bc0f4d8) 8 0x7fa78711 ??0UIStretchedTiledBackground@@QAE@KABVUString@@ABUGETextureDescription@@ABVGERectangle@@MMABVUILayoutUtility@@PAVUIForm@@K_N@Z+0xdf8 in low-level engine (0x5bc0f534) 9 0x7fa6d38f ?DrawBackground@UIForm@@MAEJABVGERectangle@@@Z+0x980 in low-level engine (0x5bc0f58c) err:dbghelp_msc:codeview_process_info Unknown CODEVIEW signature EEE6C6D5 in module empire earth.exe.norepe 10 0x00507104 in empire earth.exe.norepe (+0x107104) (0x00000000) 0x7e7fee5f: movl 0x39240(%eax),%edx
I have seen a simmilar problem in old D3D7 and I've decided that it's not worth fixing and started to rewrite D3D7 with WineD3D.
Stefan
Hi Stefan,
Stefan Dösinger wrote:
Hello, I have come across a D3D7 call where I need some help with: IDirect3DDevice::DrawIndexedPrimitiveVB. The prototype is DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface, D3DPRIMITIVETYPE d3dptPrimitiveType, LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf, DWORD dwStartVertex, DWORD dwNumVertices, LPWORD lpwIndices, DWORD dwIndexCount, DWORD dwFlags)
I can't find any usable information about it on MSDN, and there's no equivalent in other D3D versions and WineD3D.
Is there an easy translation to IWineD3DDevice::DrawIndexedPrimitive orIWineD3DDevice::DrawIndexedPrimitiveUP, or do I have to add this call to WineD3D(based on the old implementation in D3D7 perhaps?).
Since vertex buffer support is a hack, I think you can use standard wined3d drawing primitives for the moment. You just have to save/restore matrices and change vertex buffer implementation a bit.
Btw, thanks for undertaking this big task. :-)
Bye, Christian
On Fri, Oct 14, 2005 at 04:52:37PM +0100, Christian Costa wrote:
Since vertex buffer support is a hack, I think you can use standard wined3d drawing primitives for the moment.
Well, vertex buffer support is only a hack in the case of 'pre-transformed' buffers (i.e. if the application transforms the buffer without rendering it and later on renders the transformed buffers).
The only application I know of which uses this feature is MI4 (EMI).
A part from that, where is the hack located :-) ?
Lionel
PS: in theory, vertex buffers should be stored 'on card' using OpenGL extensions (for which I forgot the names)
Lionel Ulmer wrote:
On Fri, Oct 14, 2005 at 04:52:37PM +0100, Christian Costa wrote:
Since vertex buffer support is a hack, I think you can use standard wined3d drawing primitives for the moment.
Well, vertex buffer support is only a hack in the case of 'pre-transformed' buffers (i.e. if the application transforms the buffer without rendering it and later on renders the transformed buffers).
The only application I know of which uses this feature is MI4 (EMI).
I was talking about this hack (that you did some years ago :-) in the sense that full support for old d3d vertex buffers is more complicated due to ProcessVertices.
A part from that, where is the hack located :-) ?
Lionel
PS: in theory, vertex buffers should be stored 'on card' using OpenGL extensions (for which I forgot the names)
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hello, I have come across a D3D7 call where I need some help with: IDirect3DDevice::DrawIndexedPrimitiveVB. The prototype is DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface, D3DPRIMITIVETYPE d3dptPrimitiveType, LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf, DWORD dwStartVertex, DWORD dwNumVertices, LPWORD lpwIndices, DWORD dwIndexCount, DWORD dwFlags)
I can't find any usable information about it on MSDN, and there's no equivalent in other D3D versions and WineD3D.
Is there an easy translation to IWineD3DDevice::DrawIndexedPrimitive orIWineD3DDevice::DrawIndexedPrimitiveUP, or do I have to add this call to WineD3D(based on the old implementation in D3D7 perhaps?).
I think the best thing to do is to create another function in wined3d/device.c DrawIndexedPrimitiveVB that is based on DrawIndexedPrimitiveUP but either takes a IWineD3DVertexBuffer or has the caller use SetVertexBuffer and then call DrawIndexedPrimitiveVB .
e.g.
IWineD3DDeviceImpl_DrawIndexedPrimitiveVB(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, CONST void* pIndexData) { /* The rest of the code making up IWineD3DDeviceImpl_DrawIndexedPrimitiveVB */ }
DirectX7_DrawIndexedPrimitiveVB(LPDIRECT3DDEVICE7 iface, D3DPRIMITIVETYPE d3dptPrimitiveType, LPDIRECT3DVERTEXBUFFER7 lpD3DVertexBuf, DWORD dwStartVertex, DWORD dwNumVertices, LPWORD lpwIndices, DWORD dwIndexCount, DWORD dwFlags) {
IWineD3DDeviceImpl_SetStreamSource(device, 0, lpD3DVertexBuf->wineD3DVertexBuffer, dwStartVertex * lpD3DVertexBuf->stride, lpD3DVertexBuf->stride); IWineD3DDeviceImpl_DrawIndexedPrimitiveVB(device, PrimitiveType, dwIndexCount, lpwIndices); }
Or.
IWineD3DDeviceImpl_DrawIndexedPrimitiveVB(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, CONST void* pIndexData, IWineD3DVertexBuffer* pVertexBuffer, UINT dwStartVertex, UINT Stride) {
IWineD3DDeviceImpl_SetStreamSource(device, 0, pVertexBuffer, dwStartVertex * Stride, Stride); /* The rest of the code making up IWineD3DDeviceImpl_DrawIndexedPrimitiveVB */ }
IDirect3DVertexBuffer7 need to wrap wined3dVertexBuffer.
Oliver.
___________________________________________________________ Yahoo! Messenger - NEW crystal clear PC to PC calling worldwide with voicemail http://uk.messenger.yahoo.com
Hello, Just one question about thread safety: The openGL crash I am struggling with seems related to threading:
<~30000 lines of debug output from thread 0xb > 000b:trace:ddraw:Main_DirectDrawSurface_Unlock (0x7c8a3910)->Unlock((nil)) 000b:trace:d3d_surface:IWineD3DSurfaceImpl_UnlockRect (0x7c8a3cb8 ) : dirtyfied(1) 000b:fixme:d3d_surface:IWineD3DSurfaceImpl_UnlockRect unsupported unlocking to surface surf@0x7c8a3cb8 usage(512) 000b:trace:ddraw:Main_DirectDrawSurface_Unlock (0x7c8a2e60)->Unlock((nil)) 000b:trace:d3d_surface:IWineD3DSurfaceImpl_UnlockRect (0x7c8a3208 ) : dirtyfied(1) 000b:fixme:d3d_surface:IWineD3DSurfaceImpl_UnlockRect unsupported unlocking to surface surf@0x7c8a3208 usage(512) 001c:trace:ddraw:Main_IDirect3DDeviceImpl_7_Clear (0x7c7e0cd8/0x7c7e0cd8)->(00000001,0x5c59f4e4,00000002,00000000,0.000000,00000000) 001c:trace:ddraw:d3ddevice_clear (0x7c7e0cd8) Relay 001c:trace:d3d:IWineD3DDeviceImpl_Clear (0x7c833250) Count (1), pRects (0x5c59f4e4), Flags (2), Z (0.000000), Stencil (0) 001c:trace:d3d:IWineD3DDeviceImpl_Clear glEnable GL_SCISSOR_TEST call ok device.c / 4666 001c:trace:d3d:IWineD3DDeviceImpl_Clear glClearDepth call ok device.c / 4688 001c:trace:d3d:IWineD3DDeviceImpl_Clear (0x7c833250) 0x5c59f4e4 Rect=(662,430)->(0,0) glRect=(662,768), len=-662, hei=-430 001c:fixme:d3d:IWineD3DDeviceImpl_Clear >>>>>>>>>>>>>>>>> 501 from glScissor @ device.c / 4717 001c:trace:d3d:IWineD3DDeviceImpl_Clear glClear call ok device.c / 4729 001c:trace:d3d:IWineD3DDeviceImpl_Clear glDisable call ok device.c / 4756 001c:trace:ddraw:WineD3D_IDirect3DDeviceImpl_7_3T_2T_1T_BeginScene (0x7c7e0cd8/0x7c7e0cd8)->(): Relay! 001c:trace:d3d:IWineD3DDeviceImpl_BeginScene (0x7c833250) : stub 001c:trace:ddraw:WineD3D_IDirect3DDeviceImpl_7_3T_2T_SetRenderState (0x7c7e0cd8/0x7c7e0cd8)->(00000089,00000000): Relay! 001c:err:ddraw:WineD3D_IDirect3DDeviceImpl_7_3T_2T_SetRenderState Calling glBegin 001c:err:ddraw:WineD3D_IDirect3DDeviceImpl_7_3T_2T_SetRenderState Calling glEnd 001c:err:ddraw:WineD3D_IDirect3DDeviceImpl_7_3T_2T_SetRenderState Done! 001c:trace:d3d:IWineD3DDeviceImpl_SetRenderState (0x7c833250)->state = WINED3DRS_LIGHTING(137), value = 0 001c:trace:d3d:IWineD3DDeviceImpl_SetRenderState glDisable GL_LIGHTING call ok device.c / 2817 001c:err:ddraw:WineD3D_IDirect3DDeviceImpl_7_3T_2T_SetRenderState Calling glBegin ---Crash in fglrx---
The nvidia OpenGL implementation crashes in IWineD3DDeviceImpl_Clear, the fglrx implementation on the first glBegin or glReadPixels call after the thread switch - Here an injected glBegin()-glEnd call after SetRenderState.
Is WineD3D threading safe yet? Or might be the underlying OpenGL layer have problems with threading?
On the fglrx side glDisable(GL_LIGHTNING) comes into play somewhere. Without this call there's no crash, but a completely blocked X server. However, I don't think it's related to the cause, but it only changes the symptom.
Without Hardware accellerated OpenGL there's no crash in OpenGL, but there's a DIB crash later on. With the old D3D7 Implementation I've also seen texture problems after the thread switch.
Thanks, Stefan
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hello, Just one question about thread safety: The openGL crash I am struggling with seems related to threading: ---Crash in fglrx---
The nvidia OpenGL implementation crashes in IWineD3DDeviceImpl_Clear, the fglrx implementation on the first glBegin or glReadPixels call after the thread switch - Here an injected glBegin()-glEnd call after SetRenderState.
Is WineD3D threading safe yet? Or might be the underlying OpenGL layer have problems with threading?
Wined3d isn't thread safe yet. Threading will cause lots of problems because when you call MakeActive with the OpenGL context it only makes the context active on the current thread so when you switch threads you may be using a different OpenGL context. This also means that wined3d cannot support multiple concurrent devices, unless the application is using one device per thread, because the OpenGL context isn't being switched when the device changes.
Oliver.
Thanks, Stefan
___________________________________________________________ How much free photo storage do you get? Store your holiday snaps for FREE with Yahoo! Photos http://uk.photos.yahoo.com
Wined3d isn't thread safe yet. Threading will cause lots of problems because when you call MakeActive with the OpenGL context it only makes the context active on the current thread so when you switch threads you may be using a different OpenGL context. This also means that wined3d cannot support multiple concurrent devices, unless the application is using one device per thread, because the OpenGL context isn't being switched when the device changes.
I've written a little function: void check_thread(IWineD3DDeviceImpl *This) { DWORD tid = GetCurrentThreadId(); if(This->LastTid != tid) { WARN(" (%p) Current thread has changed! Updating OpenGL context\n", This); TRACE(" (%p) Old tid=0x%lx, new tid=0x%lx\n", This, This->LastTid, tid);
/* Find the implicit swapchain and restore the GL context */ if(This->swapchains) { if(This->swapchains->swapchain) { IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *) This->swapchains->swapchain; /* Restore the glX context */ if(glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx) == FALSE) { ERR("Error in setting current context (display %p context %p drawable %ld)!\n", swapchain->display, swapchain->glCtx, swapchain->win); } checkGLcall("glXMakeCurrent");
/* Todo: Restore the viewport */ } else { ERR(" (%p) Swapchain list found, but it doesn't contain a swapchain\n", This); } } else { ERR(" (%p) No swapchains found - Expect a crash\n", This); }
This->LastTid = tid; } }
It restored the glx context based on the one in the implicit swapchain. I call it in WineD3DDeviceImpl_Clear. This solved the GL crash, and I rush into a blocked Desktop in surface UnlockRect, which can only be solved by killing wine via acpi hotkeys or ssh. Eighter my solution is incorrect or these crashes are not related.
Stefan
PS: I've a Direct3D 9 test if you are interested.
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Wined3d isn't thread safe yet. Threading will cause lots of problems because when you call MakeActive with the OpenGL context it only makes the context active on the current thread so when you switch threads you may be using a different OpenGL context. This also means that wined3d cannot support multiple concurrent devices, unless the application is using one device per thread, because the OpenGL context isn't being switched when the device changes.
I've written a little function: void check_thread(IWineD3DDeviceImpl *This) { DWORD tid = GetCurrentThreadId(); if(This->LastTid != tid) { WARN(" (%p) Current thread has changed! Updating OpenGL context\n", This); TRACE(" (%p) Old tid=0x%lx, new tid=0x%lx\n", This, This->LastTid, tid);
/* Find the implicit swapchain and restore the GL context */ if(This->swapchains) { if(This->swapchains->swapchain) { IWineD3DSwapChainImpl *swapchain = (IWineD3DSwapChainImpl *)
This->swapchains->swapchain; /* Restore the glX context */ if(glXMakeCurrent(swapchain->display, swapchain->win, swapchain->glCtx) == FALSE) { ERR("Error in setting current context (display %p context %p drawable %ld)!\n", swapchain->display, swapchain->glCtx, swapchain->win); } checkGLcall("glXMakeCurrent");
/* Todo: Restore the viewport */ } else { ERR(" (%p) Swapchain list found, but it doesn't contain a
swapchain\n", This); } } else { ERR(" (%p) No swapchains found - Expect a crash\n", This); }
This->LastTid = tid; }
}
It restored the glx context based on the one in the implicit swapchain. I call it in WineD3DDeviceImpl_Clear. This solved the GL crash, and I rush into a blocked Desktop in surface UnlockRect, which can only be solved by killing wine via acpi hotkeys or ssh. Eighter my solution is incorrect or these crashes are not related.
/you should really be using the getter function to get the implicite swapchain and your function still doesn't make things threadsafe, desktop lockups are usually because ENTER_GL / LEAVE_GL's aren't correct. (I've also had some problems with ATI's drivers and buffer overruns causing X to lockup)
Stefan
PS: I've a Direct3D 9 test if you are interested.
___________________________________________________________ To help you stay safe and secure online, we've developed the all new Yahoo! Security Centre. http://uk.security.yahoo.com
On Sat, Oct 15, 2005 at 04:58:00PM +0200, Stefan Dösinger wrote:
Hello, Just one question about thread safety: The openGL crash I am struggling with seems related to threading:
Ahhhh, you fell again in the (in)famous multi-threaded D3D applications :-)
Alas, for now, this is an unsolved issue for which no clear plan is put in place. So I guess it would be best to choose another game to do your DDraw => WineD3D port as neither DDraw not WineD3D support (yet) these kind of applications.
Lionel
Am Samstag, 15. Oktober 2005 20:11 schrieben Sie:
On Sat, Oct 15, 2005 at 04:58:00PM +0200, Stefan Dösinger wrote:
Hello, Just one question about thread safety: The openGL crash I am struggling with seems related to threading:
Ahhhh, you fell again in the (in)famous multi-threaded D3D applications :-)
Alas, for now, this is an unsolved issue for which no clear plan is put in place. So I guess it would be best to choose another game to do your DDraw => WineD3D port as neither DDraw not WineD3D support (yet) these kind of applications.
Well any suggestions? I don't know many D3D7 games. There should be at least a free demo downloadable.
I'll try my wined3d glXMakeCurrent hack on old ddraw, just out of curiosity.
Stefan
On Sat, Oct 15, 2005 at 08:25:18PM +0200, Stefan Dösinger wrote:
I'll try my wined3d glXMakeCurrent hack on old ddraw, just out of curiosity.
I checked your code you sent in the other part of the thread and it seems strange... According to the man page:
BadAccess is generated if ctx was current to another thread at the time glXMakeCurrent was called. So if you are in thread B and thread A has the control of your context, doing a 'glXMakeCurrent' on the shared context should fail as the context is currently active in thread A.
To have this method work properly, one would have to somehow make 'glXMakeCurrent(NULL)' run in the context of thread A before doing what you did.
Lionel
To have this method work properly, one would have to somehow make 'glXMakeCurrent(NULL)' run in the context of thread A before doing what you did.
Threading fun.... Will be a long study of man pages and windows threading things I guess.
A wild guess: Remove the context after every function using OpenGL and aquire it at the beginning? Really bad performance I'd guess, if it works at all.
(Olivier just has sent me a useable guide for thread safety things)
Another update before sending: I've used my glXMakeCurrent hack with old ddraw, and guess what: Empire Earth brings the main menu up successfully[1]. It's slow as hell(yes, 2D DIB with those horrible ATI drivers), and it has some little drawing problems. It crashes in msacm when trying to start a game. Well, this shows that its possible - Time to make this work with WineD3D ;-)
[1] Screen shots are allways cool - www.doesi.gmxhome.de/ee-shot.png
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
To have this method work properly, one would have to somehow make 'glXMakeCurrent(NULL)' run in the context of thread A before doing what you did.
[1] Screen shots are allways cool - www.doesi.gmxhome.de/ee-shot.png
You should be able to get rid of the lines by adjusting the glTranslatef(0.9 / This->stateBlock->viewport.Width, -0.9 / This->stateBlock->viewport.Height, 0); in drawprim.c. The current code isn't quite right,
Oliver.
___________________________________________________________ Get My Web - a better way to save web pages http://uk.search.yahoo.com/myresults/default
On Sat, Oct 15, 2005 at 08:59:55PM +0200, Stefan Dösinger wrote:
Another update before sending: I've used my glXMakeCurrent hack with old ddraw, and guess what: Empire Earth brings the main menu up successfully[1]. It's slow as hell(yes, 2D DIB with those horrible ATI drivers), and it has some little drawing problems. It crashes in msacm when trying to start a game.
Well, seems that your GL drivers do not do all the checks the specification requires them to do... Lucky for you :-)
Lionel
--- Lionel Ulmer lionel.ulmer@free.fr wrote:
On Sat, Oct 15, 2005 at 04:58:00PM +0200, Stefan Dösinger wrote:
Hello, Just one question about thread safety: The openGL crash I am struggling with seems related to threading:
Ahhhh, you fell again in the (in)famous multi-threaded D3D applications :-)
Alas, for now, this is an unsolved issue for which no clear plan is put in place. So I guess it would be best to choose another game to do your DDraw => WineD3D port as neither DDraw not WineD3D support (yet) these kind of applications.
It fairly easy to make things thread safe and support multiple devices per thread, very roughly you have to:
Add the OpenGL context to the device structure. Make a per-device critical section. Whenever a call is made enter the critical section Then check that the current active context is the same as the context on the device. If not then make the device context active.
I wanted to finish state management before making things threadsafe and support multiple devices per thread.
Oliver.
Lionel
-- Lionel Ulmer - http://www.bbrox.org/
___________________________________________________________ How much free photo storage do you get? Store your holiday snaps for FREE with Yahoo! Photos http://uk.photos.yahoo.com
On Sat, Oct 15, 2005 at 07:30:34PM +0100, Oliver Stieber wrote:
Add the OpenGL context to the device structure. Make a per-device critical section. Whenever a call is made enter the critical section Then check that the current active context is the same as the context on the device. If not then make the device context active.
How did you plan to solve the 'one needs to release a context before it is free to be used in another thread' problem ?
The only 'easy' way out I can see would be to always release the context at the end of each processing so that any subsequent thread could, if needed, get the context.
Lionel
--- Lionel Ulmer lionel.ulmer@free.fr wrote:
On Sat, Oct 15, 2005 at 07:30:34PM +0100, Oliver Stieber wrote:
Add the OpenGL context to the device structure. Make a per-device critical section. Whenever a call is made enter the critical section Then check that the current active context is the same as the context on the device. If not then make the device context active.
How did you plan to solve the 'one needs to release a context before it is free to be used in another thread' problem ?
The only 'easy' way out I can see would be to always release the context at the end of each processing so that any subsequent thread could, if needed, get the context.
We could do that, or we could signal the other thread an tell it to release the context which should cut down on the context switching, I'm not sure how easy that would be to setup (it doesn't seem possible using even objects because the thread has to be waiting)
Another option would be to create a new context that shares resources with the other contexts and copy over the state from the old context to the new one.
Either way there's only a slight performance hit for single threaded applications.
Oliver.
Lionel
-- Lionel Ulmer - http://www.bbrox.org/
___________________________________________________________ How much free photo storage do you get? Store your holiday snaps for FREE with Yahoo! Photos http://uk.photos.yahoo.com
On Sat, Oct 15, 2005 at 08:13:24PM +0100, Oliver Stieber wrote:
We could do that, or we could signal the other thread an tell it to release the context which should cut down on the context switching, I'm not sure how easy that would be to setup (it doesn't seem possible using even objects because the thread has to be waiting)
Well, the 'signal' option is (AFAIK) what Transgaming does in Cedega to fix the issue.
Another option would be to create a new context that shares resources with the other contexts and copy over the state from the old context to the new one.
And this is what I planned to implement when the I have the motivation and the time (discussed about it on IRC with a guy some time ago trying to find the best way to do that).
I may try it one of these days for some specific cases (like for Dungeon Siege) and if it works, generalize to all cases.
Lionel
--- Lionel Ulmer lionel.ulmer@free.fr wrote:
On Sat, Oct 15, 2005 at 08:13:24PM +0100, Oliver Stieber wrote:
We could do that, or we could signal the other thread an tell it to release the context which should cut down on the context switching, I'm not sure how easy that would be to setup (it
doesn't
seem possible using even objects because the thread has to be waiting)
Well, the 'signal' option is (AFAIK) what Transgaming does in Cedega to fix the issue.
Another option would be to create a new context that shares resources with the other contexts
and
copy over the state from the old context to the new one.
And this is what I planned to implement when the I have the motivation and the time (discussed about it on IRC with a guy some time ago trying to find the best way to do that).
I may try it one of these days for some specific cases (like for Dungeon Siege) and if it works, generalize to all cases.
For wined3d the code in device.c:IWineD3DDeviceImpl_ActiveRender could be improved and used, it creates a new context for a render target and then applies the current state block to update the states. I've got some code that improves updating the states so that only changes are updated but it's a bit work in progress at the moment. It may be easier to do in DirectX 7 because of the way it manages states.
Oliver.
Lionel
-- Lionel Ulmer - http://www.bbrox.org/
___________________________________________________________ How much free photo storage do you get? Store your holiday snaps for FREE with Yahoo! Photos http://uk.photos.yahoo.com
On Sat, Oct 15, 2005 at 08:44:05PM +0100, Oliver Stieber wrote:
It may be easier to do in DirectX 7 because of the way it manages states.
Well, I wanted first to handle 'special cases' like applications using the second thread just to do lock / unlock on the buffer or loading textures (which is a good part of the cases). For those, no need to handle states as they are not needed anyway.
Applications that are really doing multithreaded 3D rendering are quite rare (and the only case I know is just starting with one thread and then moving to another while not using the previous one again).
Lionel
Applications that are really doing multithreaded 3D rendering are quite rare (and the only case I know is just starting with one thread and then moving to another while not using the previous one again).
Empire Earth does, contrary to the first impression, more than that. It switches the threads at least 2 times when trying to start the in-game engine.
I'll stick to Half-Life and Need for Speed 3 for my D3D7->WineD3D work ;-) Hopefully these apps aren't multithreaded too.
Stefan
Am Samstag, 15. Oktober 2005 21:13 schrieb Oliver Stieber:
--- Lionel Ulmer lionel.ulmer@free.fr wrote:
On Sat, Oct 15, 2005 at 07:30:34PM +0100, Oliver Stieber wrote:
Add the OpenGL context to the device structure. Make a per-device critical section. Whenever a call is made enter the critical section Then check that the current active context is the same as the context on the device. If not then make the device context active.
How did you plan to solve the 'one needs to release a context before it is free to be used in another thread' problem ?
The only 'easy' way out I can see would be to always release the context at the end of each processing so that any subsequent thread could, if needed, get the context.
How about creating a new thread to to all rendering, and make the calls call this thread and block until the function's finished? Is this possible?
Stefan
How about creating a new thread to to all rendering, and make the calls call this thread and block until the function's finished? Is this possible?
Yeah, this was another option we discussed (the 'marshalling' option as we called it :-) ). Was deemed too slow as it would reduce performance of games using a single-threaded rendering system (the vast majority of games).
The problem with that is either you know beforehand that it will be multi-threaded or it's too late (as once you detect it, you cannot go back as your context is already taken by the other thread).
Lionel
Hello,
I think the best thing to do is to create another function in wined3d/device.c DrawIndexedPrimitiveVB that is based on DrawIndexedPrimitiveUP but either takes a IWineD3DVertexBuffer or has the caller use SetVertexBuffer and then call DrawIndexedPrimitiveVB .
e.g.
<snip>
IWineD3DDeviceImpl_DrawIndexedPrimitiveVB(IWineD3DDevice *iface, D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, CONST void* pIndexData, IWineD3DVertexBuffer* pVertexBuffer, UINT dwStartVertex, UINT Stride) {
IWineD3DDeviceImpl_SetStreamSource(device, 0, pVertexBuffer,
dwStartVertex * Stride, Stride); /* The rest of the code making up IWineD3DDeviceImpl_DrawIndexedPrimitiveVB */ }
I have hit this function again with half-life. What is this Stride here? I haven't found anything usefull about it.
Stefan
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Hello,
I think the best thing to do is to create another function in wined3d/device.c DrawIndexedPrimitiveVB that is based on DrawIndexedPrimitiveUP but either takes a IWineD3DVertexBuffer or has the caller use SetVertexBuffer and then call DrawIndexedPrimitiveVB .
e.g.
<snip> > IWineD3DDeviceImpl_DrawIndexedPrimitiveVB(IWineD3DDevice *iface, > D3DPRIMITIVETYPE PrimitiveType, UINT MinVertexIndex, UINT NumVertices, > CONST void* pIndexData, > IWineD3DVertexBuffer* > pVertexBuffer, UINT dwStartVertex, UINT Stride) { > > IWineD3DDeviceImpl_SetStreamSource(device, 0, pVertexBuffer, > dwStartVertex * Stride, Stride); /* The rest of the code making up > IWineD3DDeviceImpl_DrawIndexedPrimitiveVB */ } I have hit this function again with half-life. What is this Stride here? I haven't found anything usefull about it.
Vertex buffers hold arrays of vertex (and possibly other) data, the stride is the size of the vertex + data stucture in bytes.
So,
struct vertexData { D3DVALUE x, y, x; /* vertixes D3DVALUE nx, ny, nz; /* normals D3DVALUE tu, tv; /* texture offsets };
struct vertexData myVertexData[5];
int main(int argv, char *argc) { char *vertexData = (char *)myVertexData; int stride = sizeof(struct vertexData);
if ((void *)(&myVertexData[2]) == (void *)(vertexData + (2 * stride))) { printf("Success\n"); } }
You'll have to use the FVF of the vertex buffer's D3DVERTEXBUFFERDESC to work out it's stride size.
Oliver.
Stefan
___________________________________________________________ To help you stay safe and secure online, we've developed the all new Yahoo! Security Centre. http://uk.security.yahoo.com
Vertex buffers hold arrays of vertex (and possibly other) data, the stride is the size of the vertex + data stucture in bytes.
Thanks for the explanation :)
Do you know any useable API documentation for Direct3D7? I can't find anything on msdn, only some fragments.
--- Stefan Dösinger stefandoesinger@gmx.at wrote:
Vertex buffers hold arrays of vertex (and possibly other) data, the stride is the size of the vertex + data stucture in bytes.
Thanks for the explanation :)
Do you know any useable API documentation for Direct3D7? I can't find anything on msdn, only some fragments.
Nope, I've done a bit of googling and can't find anything, not even someone with the SDK.
Oliver
___________________________________________________________ To help you stay safe and secure online, we've developed the all new Yahoo! Security Centre. http://uk.security.yahoo.com
Hello, I have read a little bit more into the concept of vertex buffering, and I wanted to make sure that I've understood everything correctly and ask some WineD3D questions.
According to some documents I've found on the internet and the description in the DX7 SDK, the the application uses Vertex Buffers to store some vertex declarations. Therefore it Locks() the buffer, writes some vertex data into the buffer and Unlocks() it. When it calls DrawIndexedPrimitiveVB, it tells D3D7 to render some vertices from the buffers memory, based on the index it passes.
The purpose for this is optimisation, so the graphics driver knows about the vertices in the buffer and can do some pre-calculations.
So what the implementation of DrawIndexedPrimitiveVB has to do is to read the vertex definitions from the buffer and pass it to the rendering functions. Which render function does WineD3D have? From the headers it looks like drawPrimitive() is the main function here.
Stefan