[Mesa-dev] [PATCH 22/36] st/nine: Rework buffer presentation path
Axel Davy
axel.davy at ens.fr
Wed Dec 7 22:30:45 UTC 2016
Use the new API for DISCARD.
Signed-off-by: Axel Davy <axel.davy at ens.fr>
---
src/gallium/state_trackers/nine/swapchain9.c | 180 ++++++++++++++++++++-------
1 file changed, 132 insertions(+), 48 deletions(-)
diff --git a/src/gallium/state_trackers/nine/swapchain9.c b/src/gallium/state_trackers/nine/swapchain9.c
index 431966d..79530f5 100644
--- a/src/gallium/state_trackers/nine/swapchain9.c
+++ b/src/gallium/state_trackers/nine/swapchain9.c
@@ -67,6 +67,15 @@ NineSwapChain9_ctor( struct NineSwapChain9 *This,
This->mode = NULL;
ID3DPresent_AddRef(pPresent);
+ if (!This->actx->thread_submit &&
+ This->base.device->minor_version_num > 2) {
+ D3DPRESENT_PARAMETERS2 params2;
+
+ memset(¶ms2, 0, sizeof(D3DPRESENT_PARAMETERS2));
+ params2.AllowDISCARDDelayedRelease = TRUE;
+ params2.TearFreeDISCARD = FALSE;
+ ID3DPresent_SetPresentParameters2(pPresent, ¶ms2);
+ }
if (!pPresentationParameters->hDeviceWindow)
pPresentationParameters->hDeviceWindow = hFocusWindow;
@@ -114,6 +123,10 @@ D3DWindowBuffer_create(struct NineSwapChain9 *This,
return ret;
}
+static int
+NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pParams );
+
HRESULT
NineSwapChain9_Resize( struct NineSwapChain9 *This,
D3DPRESENT_PARAMETERS *pParams,
@@ -203,12 +216,8 @@ NineSwapChain9_Resize( struct NineSwapChain9 *This,
if (hr != D3D_OK)
return hr;
- /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip.
- * Here we don't get back the initial content of the screen. To emulate the behaviour
- * we allocate an additional buffer */
oldBufferCount = This->num_back_buffers;
- newBufferCount = pParams->BackBufferCount +
- (pParams->SwapEffect != D3DSWAPEFFECT_COPY);
+ newBufferCount = NineSwapChain9_GetBackBufferCountForParams(This, pParams);
multisample_type = pParams->MultiSampleType;
@@ -799,58 +808,93 @@ NineSwapChain9_Present( struct NineSwapChain9 *This,
if (hr == D3DERR_WASSTILLDRAWING)
return hr;
- switch (This->params.SwapEffect) {
- case D3DSWAPEFFECT_FLIP:
- UNTESTED(4);
- case D3DSWAPEFFECT_DISCARD:
- /* rotate the queue */
- pipe_resource_reference(&res, This->buffers[0]->base.resource);
- for (i = 1; i < This->num_back_buffers; i++) {
- NineSurface9_SetResourceResize(This->buffers[i - 1],
- This->buffers[i]->base.resource);
- }
- NineSurface9_SetResourceResize(
- This->buffers[This->num_back_buffers - 1], res);
- pipe_resource_reference(&res, NULL);
+ if (This->base.device->minor_version_num > 2 &&
+ This->params.SwapEffect == D3DSWAPEFFECT_DISCARD &&
+ This->params.PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE &&
+ !This->actx->thread_submit) {
+ int next_buffer = -1;
- if (This->present_buffers[0]) {
- pipe_resource_reference(&res, This->present_buffers[0]);
- for (i = 1; i < This->num_back_buffers; i++)
- pipe_resource_reference(&(This->present_buffers[i-1]), This->present_buffers[i]);
- pipe_resource_reference(&(This->present_buffers[This->num_back_buffers - 1]), res);
- pipe_resource_reference(&res, NULL);
- }
-
- handle_temp = This->present_handles[0];
+ while (next_buffer == -1) {
+ /* Find a free backbuffer */
for (i = 1; i < This->num_back_buffers; i++) {
- This->present_handles[i-1] = This->present_handles[i];
+ if (ID3DPresent_IsBufferReleased(This->present, This->present_handles[i])) {
+ DBG("Found buffer released: %d\n", i);
+ next_buffer = i;
+ break;
+ }
}
- This->present_handles[This->num_back_buffers - 1] = handle_temp;
- task_temp = This->tasks[0];
- for (i = 1; i < This->num_back_buffers; i++) {
- This->tasks[i-1] = This->tasks[i];
+ if (next_buffer == -1) {
+ DBG("Found no buffer released. Waiting for event\n");
+ ID3DPresent_WaitBufferReleaseEvent(This->present);
}
- This->tasks[This->num_back_buffers - 1] = task_temp;
- break;
+ }
+ /* Switch with the released buffer */
+ pipe_resource_reference(&res, This->buffers[0]->base.resource);
+ NineSurface9_SetResourceResize(
+ This->buffers[0], This->buffers[next_buffer]->base.resource);
+ NineSurface9_SetResourceResize(
+ This->buffers[next_buffer], res);
+ pipe_resource_reference(&res, NULL);
+
+ if (This->present_buffers[0]) {
+ pipe_resource_reference(&res, This->present_buffers[0]);
+ pipe_resource_reference(&This->present_buffers[0], This->present_buffers[next_buffer]);
+ pipe_resource_reference(&This->present_buffers[next_buffer], res);
+ pipe_resource_reference(&res, NULL);
+ }
- case D3DSWAPEFFECT_COPY:
- UNTESTED(5);
- /* do nothing */
- break;
+ handle_temp = This->present_handles[0];
+ This->present_handles[0] = This->present_handles[next_buffer];
+ This->present_handles[next_buffer] = handle_temp;
- case D3DSWAPEFFECT_OVERLAY:
- /* XXX not implemented */
- break;
+ /* 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 */
+ case D3DSWAPEFFECT_FLIPEX: /* Allows optimizations over FLIP for windowed mode. */
+ case D3DSWAPEFFECT_DISCARD: /* Allows optimizations over FLIP */
+ case D3DSWAPEFFECT_FLIP:
+ /* rotate the queue */
+ pipe_resource_reference(&res, This->buffers[0]->base.resource);
+ for (i = 1; i < This->num_back_buffers; i++) {
+ NineSurface9_SetResourceResize(This->buffers[i - 1],
+ This->buffers[i]->base.resource);
+ }
+ NineSurface9_SetResourceResize(
+ This->buffers[This->num_back_buffers - 1], res);
+ pipe_resource_reference(&res, NULL);
- case D3DSWAPEFFECT_FLIPEX:
- /* XXX not implemented */
- break;
- }
+ if (This->present_buffers[0]) {
+ pipe_resource_reference(&res, This->present_buffers[0]);
+ for (i = 1; i < This->num_back_buffers; i++)
+ pipe_resource_reference(&(This->present_buffers[i-1]), This->present_buffers[i]);
+ pipe_resource_reference(&(This->present_buffers[This->num_back_buffers - 1]), res);
+ pipe_resource_reference(&res, NULL);
+ }
+
+ handle_temp = This->present_handles[0];
+ for (i = 1; i < This->num_back_buffers; i++) {
+ This->present_handles[i-1] = This->present_handles[i];
+ }
+ This->present_handles[This->num_back_buffers - 1] = handle_temp;
+ task_temp = This->tasks[0];
+ for (i = 1; i < This->num_back_buffers; i++) {
+ This->tasks[i-1] = This->tasks[i];
+ }
+ This->tasks[This->num_back_buffers - 1] = task_temp;
+ break;
+
+ case D3DSWAPEFFECT_COPY:
+ /* do nothing */
+ break;
+ }
- if (This->tasks[0])
- _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0]));
+ if (This->tasks[0])
+ _mesa_threadpool_wait_for_task(This->pool, &(This->tasks[0]));
- ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]);
+ ID3DPresent_WaitBufferReleased(This->present, This->present_handles[0]);
+ }
This->base.device->state.changed.group |= NINE_STATE_FB;
@@ -1048,3 +1092,43 @@ NineSwapChain9_WaitForThread( struct NineSwapChain9 *This,
(void) ID3DPresent_WaitForThread(This->present, thread);
}
}
+
+static int
+NineSwapChain9_GetBackBufferCountForParams( struct NineSwapChain9 *This,
+ D3DPRESENT_PARAMETERS *pParams )
+{
+ int count = pParams->BackBufferCount;
+
+ /* When we have flip behaviour, d3d9 expects we get back the screen buffer when we flip.
+ * Here we don't get back the initial content of the screen. To emulate the behaviour
+ * we allocate an additional buffer */
+ if (pParams->SwapEffect != D3DSWAPEFFECT_COPY)
+ count++;
+ /* With DISCARD, as there is no guarantee about the buffer contents, we can use
+ * an arbitrary number of buffers */
+ if (pParams->SwapEffect == D3DSWAPEFFECT_DISCARD) {
+ /* thread_submit has a throttling equivalent to the throttling
+ * with throttling_value set to count-1. Most drivers use
+ * 2 for throttling_value. For performance use count of at least 3
+ * for thread_submit. */
+ if (This->actx->thread_submit && count < 3)
+ count = 3;
+ /* When we enable AllowDISCARDDelayedRelease, we must ensure
+ * to have at least 4 buffers to meet INTERVAL_IMMEDIATE,
+ * since the display server/compositor can hold 3 buffers
+ * 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;
+ }
+
+ return count;
+}
--
2.10.2
More information about the mesa-dev
mailing list