[8/12] WineD3D: Create multithreading contexts for swapchains

Mirek thunder.m at czela.net
Wed Feb 28 01:29:23 CST 2007


Stefan Dösinger napsal(a):
> This patch finishes the opengl side of multithreaded direct3d, which was 
> started with the state management rewrite(well, almost, no offscreen rendering 
> yet) It does not make Direct3D thread safe, because there is no protection 
> against race conditions.
> 
> This patch improves multithreaded games a bit. They do not crash any more in a 
> gl call, but running them is kinda like a lottery, especially on smp systems.
> 
> Vitaly and Andras have reported success with Prince of Persia 3D: Sands of 
> Time and some other games, and on my laptop Empire Earth is running. Empire 
> Earth deadlocks regularly on my dual core system at ddraw creation.

I can even run Tom Clancy's Rainbow Six Vegas, but there are still 
problems with offscreen rendering.

Mirek

> 
> 
> ------------------------------------------------------------------------
> 
> From 49cc9a0aa6e06f559540758d5b0ed2252208a0ad Mon Sep 17 00:00:00 2001
> From: Stefan Doesinger <stefan at codeweavers.com>
> Date: Sun, 25 Feb 2007 00:18:25 +0100
> Subject: [PATCH] WineD3D: Create multithreading contexts for swapchains
> 
> This patch adds a routine to clone the main context of a swapchain to use it with a different thread on the
> same drawable. This will enable multithreaded direct3d rendering, or better enable an attempt to do that.
> From the opengl point of view it will work, but because concurrency control is not implemented yet(appart
> of ENTER_GL() / LEAVE_GL() ) games may crash randomly, show strange behavior, ...
> 
> The other problem is that this code was only tested with the open source radeon driver yet. While what
> wined3d is doing here should be allowed by the spec, some drivers may have some bugs when using multiple
> contexts on one drawable.
> ---
>  dlls/wined3d/context.c         |    4 ++--
>  dlls/wined3d/swapchain.c       |   30 ++++++++++++++++++++++++++++++
>  dlls/wined3d/wined3d_private.h |    2 ++
>  3 files changed, 34 insertions(+), 2 deletions(-)
> 
> diff --git a/dlls/wined3d/context.c b/dlls/wined3d/context.c
> index 3a815b3..8545568 100644
> --- a/dlls/wined3d/context.c
> +++ b/dlls/wined3d/context.c
> @@ -626,8 +626,8 @@ void ActivateContext(IWineD3DDeviceImpl *This, IWineD3DSurface *target, ContextU
>                  }
>  
>                  if(!context) {
> -                    /* TODO: Create a new context for the thread */
> -                    FIXME("Context creation for a new thread not implemented yet\n");
> +                    /* Create a new context for the thread */
> +                    context = IWineD3DSwapChainImpl_CreateContextForThread(swapchain);
>                  }
>              } else {
>                  context = ((IWineD3DSwapChainImpl *) swapchain)->context[0];
> diff --git a/dlls/wined3d/swapchain.c b/dlls/wined3d/swapchain.c
> index 2977a05..3b8e3e8 100644
> --- a/dlls/wined3d/swapchain.c
> +++ b/dlls/wined3d/swapchain.c
> @@ -510,3 +510,33 @@ const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl =
>      IWineD3DSwapChainImpl_SetGammaRamp,
>      IWineD3DSwapChainImpl_GetGammaRamp
>  };
> +
> +WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface) {
> +    WineD3DContext *ctx;
> +    IWineD3DSwapChainImpl *This = (IWineD3DSwapChainImpl *) iface;
> +    WineD3DContext **newArray;
> +
> +    TRACE("Creating a new context for swapchain %p, thread %d\n", This, GetCurrentThreadId());
> +
> +    ctx = CreateContext(This->wineD3DDevice, (IWineD3DSurfaceImpl *) This->frontBuffer,
> +                        This->context[0]->display, This->win);
> +    if(!ctx) {
> +        ERR("Failed to create a new context for the swapchain\n");
> +        return NULL;
> +    }
> +
> +    newArray = HeapAlloc(GetProcessHeap(), 0, sizeof(*newArray) * This->num_contexts + 1);
> +    if(!newArray) {
> +        ERR("Out of memory when trying to allocate a new context array\n");
> +        DestroyContext(This->wineD3DDevice, ctx);
> +        return NULL;
> +    }
> +    memcpy(newArray, This->context, sizeof(*newArray) * This->num_contexts);
> +    HeapFree(GetProcessHeap(), 0, This->context);
> +    newArray[This->num_contexts] = ctx;
> +    This->context = newArray;
> +    This->num_contexts++;
> +
> +    TRACE("Returning context %p\n", ctx);
> +    return ctx;
> +}
> diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
> index 45e69bf..fa4232c 100644
> --- a/dlls/wined3d/wined3d_private.h
> +++ b/dlls/wined3d/wined3d_private.h
> @@ -1341,6 +1341,8 @@ typedef struct IWineD3DSwapChainImpl
>  
>  extern const IWineD3DSwapChainVtbl IWineD3DSwapChain_Vtbl;
>  
> +WineD3DContext *IWineD3DSwapChainImpl_CreateContextForThread(IWineD3DSwapChain *iface);
> +
>  /*****************************************************************************
>   * Utility function prototypes 
>   */
> 
> 
> ------------------------------------------------------------------------
> 
> 



More information about the wine-devel mailing list