summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAxel Davy <davyaxel0@gmail.com>2021-03-05 18:23:08 +0100
committerMarge Bot <eric+marge@anholt.net>2021-03-13 21:23:24 +0000
commit634adfa253d3fbb3d6dfd9508658076ed56c7b95 (patch)
treea29eaac8e537e9d32a8253583e53c9fcb9821c7c
parent2497195aabf49c3899d6657c322f9ee2f4553bfc (diff)
st/nine: Optimize EndScene
So far we did nothing on EndScene, but the API doc says it flushes the GPU command queue. The doc implies one can optimize CPU usage by calling EndScene long before Present() is called. Implementing the flush behaviour gives me +15-20% on the CPU limited Halo. On the other hand, do limit the flush to only once per frame. 3DMark03/3Mark05 get a 2% perf hit with the patch, but 5% if I allow more flushes. Signed-off-by: Axel Davy <davyaxel0@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9451>
-rw-r--r--src/gallium/frontends/nine/device9.c13
-rw-r--r--src/gallium/frontends/nine/device9.h1
-rw-r--r--src/gallium/frontends/nine/nine_state.c17
-rw-r--r--src/gallium/frontends/nine/nine_state.h7
-rw-r--r--src/gallium/frontends/nine/swapchain9.c1
5 files changed, 39 insertions, 0 deletions
diff --git a/src/gallium/frontends/nine/device9.c b/src/gallium/frontends/nine/device9.c
index 9b44b9827b7..2de8d50ef68 100644
--- a/src/gallium/frontends/nine/device9.c
+++ b/src/gallium/frontends/nine/device9.c
@@ -2035,6 +2035,19 @@ NineDevice9_EndScene( struct NineDevice9 *This )
DBG("This=%p\n", This);
user_assert(This->in_scene, D3DERR_INVALIDCALL);
This->in_scene = FALSE;
+ This->end_scene_since_present++;
+ /* EndScene() is supposed to flush the GPU commands.
+ * The idea is to flush ahead of the Present() call.
+ * (Apps could take advantage of this by inserting CPU
+ * work between EndScene() and Present()).
+ * Most apps will have one EndScene per frame.
+ * Some will have 2 or 3.
+ * Some bad behaving apps do a lot of them.
+ * As flushing has a cost, do it only once. */
+ if (This->end_scene_since_present <= 1) {
+ nine_context_pipe_flush(This);
+ nine_csmt_flush(This);
+ }
return D3D_OK;
}
diff --git a/src/gallium/frontends/nine/device9.h b/src/gallium/frontends/nine/device9.h
index 974251f3fe9..876728e0105 100644
--- a/src/gallium/frontends/nine/device9.h
+++ b/src/gallium/frontends/nine/device9.h
@@ -90,6 +90,7 @@ struct NineDevice9
boolean is_recording;
boolean in_scene;
+ unsigned end_scene_since_present;
uint16_t vs_const_size;
uint16_t ps_const_size;
diff --git a/src/gallium/frontends/nine/nine_state.c b/src/gallium/frontends/nine/nine_state.c
index 6f57b19e1aa..0d1f670e946 100644
--- a/src/gallium/frontends/nine/nine_state.c
+++ b/src/gallium/frontends/nine/nine_state.c
@@ -211,6 +211,16 @@ nine_csmt_process( struct NineDevice9 *device )
nine_csmt_wait_processed(ctx);
}
+void
+nine_csmt_flush( struct NineDevice9* device )
+{
+ if (!device->csmt_active)
+ return;
+
+ nine_queue_flush(device->csmt_ctx->pool);
+}
+
+
/* Destroys a CSMT context.
* Waits for the worker thread to terminate.
*/
@@ -2648,6 +2658,13 @@ nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *que
return ret;
}
+CSMT_ITEM_NO_WAIT(nine_context_pipe_flush)
+{
+ struct nine_context *context = &device->context;
+
+ context->pipe->flush(context->pipe, NULL, PIPE_FLUSH_ASYNC);
+}
+
/* State defaults */
static const DWORD nine_render_state_defaults[NINED3DRS_LAST + 1] =
diff --git a/src/gallium/frontends/nine/nine_state.h b/src/gallium/frontends/nine/nine_state.h
index cc76bef3418..d42bfbfefc9 100644
--- a/src/gallium/frontends/nine/nine_state.h
+++ b/src/gallium/frontends/nine/nine_state.h
@@ -604,6 +604,9 @@ nine_context_get_query_result(struct NineDevice9 *device, struct pipe_query *que
unsigned *counter, boolean flush, boolean wait,
union pipe_query_result *result);
+void
+nine_context_pipe_flush(struct NineDevice9 *device);
+
void nine_state_restore_non_cso(struct NineDevice9 *device);
void nine_state_set_defaults(struct NineDevice9 *, const D3DCAPS9 *,
boolean is_reset);
@@ -648,9 +651,13 @@ nine_csmt_create( struct NineDevice9 *This );
void
nine_csmt_destroy( struct NineDevice9 *This, struct csmt_context *ctx );
+/* Flushes and waits everything is executed */
void
nine_csmt_process( struct NineDevice9 *This );
+/* Flushes and doesn't wait */
+void
+nine_csmt_flush( struct NineDevice9 *This );
/* Get the pipe_context (should not be called from the worker thread).
* All the work in the worker thread is finished before returning. */
diff --git a/src/gallium/frontends/nine/swapchain9.c b/src/gallium/frontends/nine/swapchain9.c
index 39784738895..44aa75a949b 100644
--- a/src/gallium/frontends/nine/swapchain9.c
+++ b/src/gallium/frontends/nine/swapchain9.c
@@ -930,6 +930,7 @@ bypass_rendering:
if (FAILED(hr)) { UNTESTED(3);return hr; }
}
+ This->base.device->end_scene_since_present = 0;
return D3D_OK;
}