summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/dri/i965/brw_conditional_render.c
diff options
context:
space:
mode:
authorNeil Roberts <neil@linux.intel.com>2014-11-04 19:15:00 +0000
committerNeil Roberts <neil@linux.intel.com>2015-05-12 11:20:47 +0100
commit426023050d1d3cd1b5fc0b3508dd7e1ee3b061e7 (patch)
treeef111be39504678c5ef9eadc505898bd620fb38f /src/mesa/drivers/dri/i965/brw_conditional_render.c
parent9585879d46fe412cbcfd50510e59e8ffe85b055f (diff)
downloadexternal_mesa3d-426023050d1d3cd1b5fc0b3508dd7e1ee3b061e7.zip
external_mesa3d-426023050d1d3cd1b5fc0b3508dd7e1ee3b061e7.tar.gz
external_mesa3d-426023050d1d3cd1b5fc0b3508dd7e1ee3b061e7.tar.bz2
i965: Use predicate enable bit for conditional rendering w/o stalling
Previously whenever a primitive is drawn the driver would call _mesa_check_conditional_render which blocks waiting for the result of the query to determine whether to render. On Gen7+ there is a bit in the 3DPRIMITIVE command which can be used to disable the primitive based on the value of a state bit. This state bit can be set based on whether two registers have different values using the MI_PREDICATE command. We can load these two registers with the pixel count values stored in the query begin and end to implement conditional rendering without stalling. Unfortunately these two source registers were not in the whitelist of available registers in the kernel driver until v3.19. This patch uses the command parser version from intel_screen to detect whether to attempt to set the predicate data registers. The predicate enable bit is currently only used for drawing 3D primitives. For blits, clears, bitmaps, copypixels and drawpixels it still causes a stall. For most of these it would probably just work to call the new brw_check_conditional_render function instead of _mesa_check_conditional_render because they already work in terms of rendering primitives. However it's a bit trickier for blits because it can use the BLT ring or the blorp codepath. I think these operations are less useful for conditional rendering than rendering primitives so it might be best to leave it for a later patch. v2: Use the command parser version to detect whether we can write to the predicate data registers instead of trying to execute a register load command. v3: Simple rebase v4: Changes suggested by Kenneth Graunke: Split the load_64bit_register function out to a separate patch so it can be a shared public function. Avoid calling _mesa_check_conditional_render if we've already determined that there's no query object. Some styling fixes. Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_conditional_render.c')
-rw-r--r--src/mesa/drivers/dri/i965/brw_conditional_render.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_conditional_render.c b/src/mesa/drivers/dri/i965/brw_conditional_render.c
new file mode 100644
index 0000000..6d37c3b
--- /dev/null
+++ b/src/mesa/drivers/dri/i965/brw_conditional_render.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Neil Roberts <neil@linux.intel.com>
+ */
+
+/** @file brw_conditional_render.c
+ *
+ * Support for conditional rendering based on query objects
+ * (GL_NV_conditional_render, GL_ARB_conditional_render_inverted) on Gen7+.
+ */
+
+#include "main/imports.h"
+#include "main/condrender.h"
+
+#include "brw_context.h"
+#include "brw_defines.h"
+#include "intel_batchbuffer.h"
+
+static void
+set_predicate_enable(struct brw_context *brw,
+ bool value)
+{
+ if (value)
+ brw->predicate.state = BRW_PREDICATE_STATE_RENDER;
+ else
+ brw->predicate.state = BRW_PREDICATE_STATE_DONT_RENDER;
+}
+
+static void
+set_predicate_for_result(struct brw_context *brw,
+ struct brw_query_object *query,
+ bool inverted)
+{
+ int load_op;
+
+ assert(query->bo != NULL);
+
+ brw_load_register_mem64(brw,
+ MI_PREDICATE_SRC0,
+ query->bo,
+ I915_GEM_DOMAIN_INSTRUCTION,
+ 0, /* write domain */
+ 0 /* offset */);
+ brw_load_register_mem64(brw,
+ MI_PREDICATE_SRC1,
+ query->bo,
+ I915_GEM_DOMAIN_INSTRUCTION,
+ 0, /* write domain */
+ 8 /* offset */);
+
+ if (inverted)
+ load_op = MI_PREDICATE_LOADOP_LOAD;
+ else
+ load_op = MI_PREDICATE_LOADOP_LOADINV;
+
+ BEGIN_BATCH(1);
+ OUT_BATCH(GEN7_MI_PREDICATE |
+ load_op |
+ MI_PREDICATE_COMBINEOP_SET |
+ MI_PREDICATE_COMPAREOP_SRCS_EQUAL);
+ ADVANCE_BATCH();
+
+ brw->predicate.state = BRW_PREDICATE_STATE_USE_BIT;
+}
+
+static void
+brw_begin_conditional_render(struct gl_context *ctx,
+ struct gl_query_object *q,
+ GLenum mode)
+{
+ struct brw_context *brw = brw_context(ctx);
+ struct brw_query_object *query = (struct brw_query_object *) q;
+ bool inverted;
+
+ if (!brw->predicate.supported)
+ return;
+
+ switch (mode) {
+ case GL_QUERY_WAIT:
+ case GL_QUERY_NO_WAIT:
+ case GL_QUERY_BY_REGION_WAIT:
+ case GL_QUERY_BY_REGION_NO_WAIT:
+ inverted = false;
+ break;
+ case GL_QUERY_WAIT_INVERTED:
+ case GL_QUERY_NO_WAIT_INVERTED:
+ case GL_QUERY_BY_REGION_WAIT_INVERTED:
+ case GL_QUERY_BY_REGION_NO_WAIT_INVERTED:
+ inverted = true;
+ break;
+ default:
+ unreachable("Unexpected conditional render mode");
+ }
+
+ /* If there are already samples from a BLT operation or if the query object
+ * is ready then we can avoid looking at the values in the buffer and just
+ * decide whether to draw using the CPU without stalling.
+ */
+ if (query->Base.Result || query->Base.Ready)
+ set_predicate_enable(brw, (query->Base.Result != 0) ^ inverted);
+ else
+ set_predicate_for_result(brw, query, inverted);
+}
+
+static void
+brw_end_conditional_render(struct gl_context *ctx,
+ struct gl_query_object *q)
+{
+ struct brw_context *brw = brw_context(ctx);
+
+ /* When there is no longer a conditional render in progress it should
+ * always render.
+ */
+ brw->predicate.state = BRW_PREDICATE_STATE_RENDER;
+}
+
+void
+brw_init_conditional_render_functions(struct dd_function_table *functions)
+{
+ functions->BeginConditionalRender = brw_begin_conditional_render;
+ functions->EndConditionalRender = brw_end_conditional_render;
+}
+
+bool
+brw_check_conditional_render(struct brw_context *brw)
+{
+ if (brw->predicate.supported) {
+ /* In some cases it is possible to determine that the primitives should
+ * be skipped without needing the predicate enable bit and still without
+ * stalling.
+ */
+ return brw->predicate.state != BRW_PREDICATE_STATE_DONT_RENDER;
+ } else if (brw->ctx.Query.CondRenderQuery) {
+ perf_debug("Conditional rendering is implemented in software and may "
+ "stall.\n");
+ return _mesa_check_conditional_render(&brw->ctx);
+ } else {
+ return true;
+ }
+}