diff options
author | Axel Davy <[email protected]> | 2018-11-10 11:42:39 +0100 |
---|---|---|
committer | Axel Davy <[email protected]> | 2018-11-21 19:55:28 +0100 |
commit | d304f0aa310ce9564ca2b677adb8c55ff0f6f0b6 (patch) | |
tree | ce831480b94043a2d28a91d093ab5b4181963bb2 /src/gallium/state_trackers | |
parent | 19af208c7de52561ec8ecb99b61e799ffe4ef67c (diff) |
st/nine: Allow 'triple buffering' with thread_submit
The path allowing triple buffering behaviour wasn't implemented
yet for thread_submit
Signed-off-by: Axel Davy <[email protected]>
Tested-by: Andre Heider <[email protected]>
Diffstat (limited to 'src/gallium/state_trackers')
-rw-r--r-- | src/gallium/state_trackers/nine/swapchain9.c | 66 | ||||
-rw-r--r-- | src/gallium/state_trackers/nine/swapchain9.h | 1 |
2 files changed, 50 insertions, 17 deletions
diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c index 0958a907013..d330c855726 100644 --- a/src/gallium/state_trackers/nine/swapchain9.c +++ b/src/gallium/state_trackers/nine/swapchain9.c @@ -28,6 +28,7 @@ #include "nine_pipe.h" #include "nine_dump.h" +#include "util/u_atomic.h" #include "util/u_inlines.h" #include "util/u_surface.h" #include "hud/hud_context.h" @@ -50,6 +51,7 @@ NineSwapChain9_ctor( struct NineSwapChain9 *This, D3DDISPLAYMODEEX *mode ) { HRESULT hr; + int i; DBG("This=%p pDevice=%p pPresent=%p pCTX=%p hFocusWindow=%p\n", This, pParams->device, pPresent, pCTX, hFocusWindow); @@ -65,8 +67,7 @@ NineSwapChain9_ctor( struct NineSwapChain9 *This, This->mode = NULL; ID3DPresent_AddRef(pPresent); - if (!This->actx->thread_submit && - This->base.device->minor_version_num > 2) { + if (This->base.device->minor_version_num > 2) { D3DPRESENT_PARAMETERS2 params2; memset(¶ms2, 0, sizeof(D3DPRESENT_PARAMETERS2)); @@ -80,6 +81,11 @@ NineSwapChain9_ctor( struct NineSwapChain9 *This, This->rendering_done = FALSE; This->pool = NULL; + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + This->pending_presentation[i] = calloc(1, sizeof(BOOL)); + if (!This->pending_presentation[i]) + return E_OUTOFMEMORY; + } return NineSwapChain9_Resize(This, pPresentationParameters, mode); } @@ -508,6 +514,11 @@ NineSwapChain9_dtor( struct NineSwapChain9 *This ) if (This->pool) _mesa_threadpool_destroy(This, This->pool); + for (i = 0; i < D3DPRESENT_BACK_BUFFERS_MAX_EX + 1; i++) { + if (This->pending_presentation[i]) + FREE(This->pending_presentation[i]); + } + for (i = 0; i < This->num_back_buffers; i++) { if (This->buffers[i]) NineUnknown_Detach(NineUnknown(This->buffers[i])); @@ -619,6 +630,7 @@ struct end_present_struct { struct pipe_fence_handle *fence_to_wait; ID3DPresent *present; D3DWindowBuffer *present_handle; + BOOL *pending_presentation; HWND hDestWindowOverride; }; @@ -630,6 +642,7 @@ static void work_present(void *data) work->screen->fence_reference(work->screen, &(work->fence_to_wait), NULL); } ID3DPresent_PresentBuffer(work->present, work->present_handle, work->hDestWindowOverride, NULL, NULL, NULL, 0); + p_atomic_set(work->pending_presentation, FALSE); free(work); } @@ -643,6 +656,8 @@ static void pend_present(struct NineSwapChain9 *This, work->present = This->present; work->present_handle = This->present_handles[0]; work->hDestWindowOverride = hDestWindowOverride; + work->pending_presentation = This->pending_presentation[0]; + p_atomic_set(work->pending_presentation, TRUE); This->tasks[0] = _mesa_threadpool_queue_task(This->pool, work_present, work); return; @@ -817,6 +832,7 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, struct pipe_resource *res = NULL; D3DWindowBuffer *handle_temp; struct threadpool_task *task_temp; + BOOL *pending_presentation_temp; int i; HRESULT hr; @@ -850,14 +866,14 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, if (This->base.device->minor_version_num > 2 && This->params.SwapEffect == D3DSWAPEFFECT_DISCARD && - This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE && - !This->actx->thread_submit) { + This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) { int next_buffer = -1; while (next_buffer == -1) { /* Find a free backbuffer */ for (i = 1; i < This->num_back_buffers; i++) { - if (ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) { + if (!p_atomic_read(This->pending_presentation[i]) && + ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) { DBG("Found buffer released: %d\n", i); next_buffer = i; break; @@ -868,6 +884,17 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, ID3DPresent_WaitBufferReleaseEvent(This->present); } } + + /* Free the task (we already checked it is finished) */ + if (This->tasks[next_buffer]) + _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[next_buffer])); + assert(!*This->pending_presentation[next_buffer] && !This->tasks[next_buffer]); + This->tasks[next_buffer] = This->tasks[0]; + This->tasks[0] = NULL; + pending_presentation_temp = This->pending_presentation[next_buffer]; + This->pending_presentation[next_buffer] = This->pending_presentation[0]; + This->pending_presentation[0] = pending_presentation_temp; + /* Switch with the released buffer */ pipe_resource_reference(&res, This->buffers[0]->base.resource); NineSurface9_SetResourceResize( @@ -886,9 +913,6 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, handle_temp = This->present_handles[0]; This->present_handles[0] = This->present_handles[next_buffer]; This->present_handles[next_buffer] = handle_temp; - - /* Path not yet compatible with thread_submit */ - assert(!This->tasks[0] && !This->tasks[next_buffer]); } else { switch (This->params.SwapEffect) { case D3DSWAPEFFECT_OVERLAY: /* Not implemented, fallback to FLIP */ @@ -923,6 +947,11 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, This->tasks[i-1] = This->tasks[i]; } This->tasks[This->num_back_buffers - 1] = task_temp; + pending_presentation_temp = This->pending_presentation[0]; + for (i = 1; i < This->num_back_buffers; i++) { + This->pending_presentation[i-1] = This->pending_presentation[i]; + } + This->pending_presentation[This->num_back_buffers - 1] = pending_presentation_temp; break; case D3DSWAPEFFECT_COPY: @@ -932,6 +961,7 @@ NineSwapChain9_Present( struct NineSwapChain9 *This, if (This->tasks[0]) _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0])); + assert(!*This->pending_presentation[0]); ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]); } @@ -1159,15 +1189,17 @@ NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This, * without releasing them: * . Buffer on screen. * . Buffer scheduled kernel side to be next on screen. - * . Last buffer sent. - * For some reasons, 5 buffers are actually needed, because in - * case a pageflip is missed because rendering wasn't finished, - * the Xserver will hold 4 buffers. */ - if (!This->actx->thread_submit && - This->base.device->minor_version_num > 2 && - pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE && - count < 5) - count = 5; + * . Last buffer sent. */ + if (This->base.device->minor_version_num > 2 && + pParams->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE) { + if (This->actx->thread_submit && count < 4) + count = 4; + /* When thread_submit is not used, 5 buffers are actually needed, + * because in case a pageflip is missed because rendering wasn't finished, + * the Xserver will hold 4 buffers. */ + else if (!This->actx->thread_submit && count < 5) + count = 5; + } } return count; diff --git a/src/gallium/state_trackers/nine/swapchain9.h b/src/gallium/state_trackers/nine/swapchain9.h index 0cd3824ea9e..0fa0589d3b7 100644 --- a/src/gallium/state_trackers/nine/swapchain9.h +++ b/src/gallium/state_trackers/nine/swapchain9.h @@ -72,6 +72,7 @@ struct NineSwapChain9 struct threadpool *pool; struct threadpool_task *tasks[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; + BOOL *pending_presentation[D3DPRESENT_BACK_BUFFERS_MAX_EX + 1]; BOOL enable_threadpool; }; |