summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/nine/swapchain9.c
diff options
context:
space:
mode:
authorAxel Davy <[email protected]>2014-11-17 16:58:29 +0100
committerEmil Velikov <[email protected]>2014-11-18 02:02:54 +0000
commit7f565845a1f3ec871cccee88e2acf6be2e429797 (patch)
treee6aa710a658af3c40561d3a7bd495ef45a3f3b81 /src/gallium/state_trackers/nine/swapchain9.c
parent948e6c522827b64cfd9b02eb3ab34e7d1f145017 (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.c86
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;