diff options
author | Axel Davy <[email protected]> | 2014-11-17 16:58:29 +0100 |
---|---|---|
committer | Emil Velikov <[email protected]> | 2014-11-18 02:02:54 +0000 |
commit | 7f565845a1f3ec871cccee88e2acf6be2e429797 (patch) | |
tree | e6aa710a658af3c40561d3a7bd495ef45a3f3b81 /src/gallium/state_trackers/nine/swapchain9.c | |
parent | 948e6c522827b64cfd9b02eb3ab34e7d1f145017 (diff) |
nine: Implement threadpool
DRI_PRIME setups have different issues due the lack of dma-buf fences
support in the drivers. For DRI3 DRI_PRIME, a race can appear, making
tearings visible, or worse showing older content than expected. Until
dma-buf fences are well supported (and by all drivers), an alternative
is to send the buffers to the server only when rendering has finished.
Since waiting the rendering has finished in the main thread has a
performance impact, this patch uses an additional thread to offload the
wait and the sending of the buffers to the server.
Acked-by: Jose Fonseca <[email protected]>
Reviewed-by: David Heidelberg <[email protected]>
Signed-off-by: Axel Davy <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers/nine/swapchain9.c')
-rw-r--r-- | src/gallium/state_trackers/nine/swapchain9.c | 86 |
1 files changed, 77 insertions, 9 deletions
diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c index ce92a3a8966..b6f5ef65782 100644 --- a/src/gallium/state_trackers/nine/swapchain9.c +++ b/src/gallium/state_trackers/nine/swapchain9.c @@ -33,6 +33,8 @@ #include "hud/hud_context.h" #include "state_tracker/drm_driver.h" +#include "threadpool.h" + #define DBG_CHANNEL DBG_SWAPCHAIN #define UNTESTED(n) DBG("UNTESTED point %d. Please tell if it worked\n", n) @@ -70,6 +72,7 @@ NineSwapChain9_ctor( struct NineSwapChain9 *This, pPresentationParameters->hDeviceWindow = hFocusWindow; This->rendering_done = FALSE; + This->pool = NULL; return NineSwapChain9_Resize(This, pPresentationParameters, mode); } @@ -227,6 +230,21 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This, desc.Width = pParams->BackBufferWidth; desc.Height = pParams->BackBufferHeight; + if (This->pool) { + _mesa_threadpool_destroy(This->pool); + This->pool = NULL; + } + This->enable_threadpool = This->actx->thread_submit && (pParams->SwapEffect != D3DSWAPEFFECT_COPY); + if (This->enable_threadpool) + This->pool = _mesa_threadpool_create(); + if (!This->pool) + This->enable_threadpool = FALSE; + + This->tasks = REALLOC(This->tasks, + oldBufferCount * sizeof(struct threadpool_task *), + newBufferCount * sizeof(struct threadpool_task *)); + memset(This->tasks, 0, newBufferCount * sizeof(struct threadpool_task *)); + for (i = 0; i < oldBufferCount; i++) { ID3DPresent_DestroyD3DWindowBuffer(This->present, This->present_handles[i]); This->present_handles[i] = NULL; @@ -444,6 +462,9 @@ NineSwapChain9_dtor( struct NineSwapChain9 *This ) DBG("This=%p\n", This); + if (This->pool) + _mesa_threadpool_destroy(This->pool); + if (This->buffers) { for (i = 0; i < This->params.BackBufferCount; i++) { NineUnknown_Destroy(NineUnknown(This->buffers[i])); @@ -541,6 +562,40 @@ handle_draw_cursor_and_hud( struct NineSwapChain9 *This, struct pipe_resource *r } } +struct end_present_struct { + struct pipe_screen *screen; + struct pipe_fence_handle *fence_to_wait; + ID3DPresent *present; + D3DWindowBuffer *present_handle; + HWND hDestWindowOverride; +}; + +static void work_present(void *data) +{ + struct end_present_struct *work = data; + if (work->fence_to_wait) { + (void) work->screen->fence_finish(work->screen, work->fence_to_wait, PIPE_TIMEOUT_INFINITE); + work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL); + } + ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0); + free(work); +} + +static void pend_present(struct NineSwapChain9 *This, + HWND hDestWindowOverride) +{ + struct end_present_struct *work = calloc(1, sizeof(struct end_present_struct)); + + work->screen = This->screen; + work->fence_to_wait = swap_fences_pop_front(This); + work->present = This->present; + work->present_handle = This->present_handles[0]; + work->hDestWindowOverride = hDestWindowOverride; + This->tasks[0] = _mesa_threadpool_queue_task(This->pool, work_present, work); + + return; +} + static INLINE HRESULT present( struct NineSwapChain9 *This, const RECT *pSourceRect, @@ -642,21 +697,26 @@ bypass_rendering: return D3DERR_WASSTILLDRAWING; } - fence = swap_fences_pop_front(This); - if (fence) { - (void) This->screen->fence_finish(This->screen, fence, PIPE_TIMEOUT_INFINITE); - This->screen->fence_reference(This->screen, &fence, NULL); - } - if (This->present_buffers) resource = This->present_buffers[0]; else resource = This->buffers[0]->base.resource; This->pipe->flush_resource(This->pipe, resource); - hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags); - if (FAILED(hr)) { UNTESTED(3);return hr; } + if (!This->enable_threadpool) { + This->tasks[0]=NULL; + fence = swap_fences_pop_front(This); + if (fence) { + (void) This->screen->fence_finish(This->screen, fence, PIPE_TIMEOUT_INFINITE); + This->screen->fence_reference(This->screen, &fence, NULL); + } + + hr = ID3DPresent_PresentBuffer(This->present, This->present_handles[0], hDestWindowOverride, pSourceRect, pDestRect, pDirtyRegion, dwFlags); + if (FAILED(hr)) { UNTESTED(3);return hr; } + } else { + pend_present(This, hDestWindowOverride); + } This->rendering_done = FALSE; return D3D_OK; @@ -672,8 +732,8 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, { struct pipe_resource *res = NULL; D3DWindowBuffer *handle_temp; + struct threadpool_task *task_temp; int i; - BOOL released; HRESULT hr = present(This, pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion, dwFlags); @@ -707,6 +767,11 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, This->present_handles[i-1] = This->present_handles[i]; } This->present_handles[This->params.BackBufferCount] = handle_temp; + task_temp = This->tasks[0]; + for (i = 1; i <= This->params.BackBufferCount; i++) { + This->tasks[i-1] = This->tasks[i]; + } + This->tasks[This->params.BackBufferCount] = task_temp; break; case D3DSWAPEFFECT_COPY: @@ -723,6 +788,9 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, break; } + if (This->tasks[0]) + _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0])); + ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]); This->base.device->state.changed.group |= NINE_STATE_FB; |