i965: Add support for xfb overflow query on conditional render.
authorRafael Antognolli <rafael.antognolli@intel.com>
Fri, 20 Jan 2017 17:53:26 +0000 (09:53 -0800)
committerKenneth Graunke <kenneth@whitecape.org>
Wed, 22 Feb 2017 00:28:32 +0000 (16:28 -0800)
Enable the use of a transform feedback overflow query with
glBeginConditionalRender. The render commands will only execute if the
query is true (i.e. if there was an overflow).

Use ARB_conditional_render_inverted to change this behavior.

v4:
    - reuse MI_MATH calcs from hsw_queryob (Kenneth)
    - fallback to software conditional rendering when MI_MATH is not
      available (Kenneth)

v5:
    - check query->Target (Kenneth)

Signed-off-by: Rafael Antognolli <rafael.antognolli@intel.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_conditional_render.c

index 122a4ecc0f651c9b90ca3ea7295a9d252589ce06..046a42b5f52076f75c2b875a8c87dfece73ceb75 100644 (file)
@@ -48,20 +48,19 @@ set_predicate_enable(struct brw_context *brw,
 }
 
 static void
-set_predicate_for_result(struct brw_context *brw,
-                         struct brw_query_object *query,
-                         bool inverted)
+set_predicate_for_overflow_query(struct brw_context *brw,
+                                 struct brw_query_object *query,
+                                 int stream_start, int count)
 {
-   int load_op;
-
-   assert(query->bo != NULL);
-
-   /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
-    * command when loading the values into the predicate source registers for
-    * conditional rendering.
-    */
-   brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
+   hsw_overflow_result_to_gpr0(brw, query, count);
+   brw_load_register_reg64(brw, HSW_CS_GPR(0), MI_PREDICATE_SRC0);
+   brw_load_register_imm64(brw, MI_PREDICATE_SRC1, 0ull);
+}
 
+static void
+set_predicate_for_occlusion_query(struct brw_context *brw,
+                                  struct brw_query_object *query)
+{
    brw_load_register_mem64(brw,
                            MI_PREDICATE_SRC0,
                            query->bo,
@@ -74,6 +73,34 @@ set_predicate_for_result(struct brw_context *brw,
                            I915_GEM_DOMAIN_INSTRUCTION,
                            0, /* write domain */
                            8 /* offset */);
+}
+
+static void
+set_predicate_for_result(struct brw_context *brw,
+                         struct brw_query_object *query,
+                         bool inverted)
+{
+
+   int load_op;
+
+   assert(query->bo != NULL);
+
+   /* Needed to ensure the memory is coherent for the MI_LOAD_REGISTER_MEM
+    * command when loading the values into the predicate source registers for
+    * conditional rendering.
+    */
+   brw_emit_pipe_control_flush(brw, PIPE_CONTROL_FLUSH_ENABLE);
+
+   switch (query->Base.Target) {
+   case GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB:
+      set_predicate_for_overflow_query(brw, query, 0, 1);
+      break;
+   case GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB:
+      set_predicate_for_overflow_query(brw, query, 0, MAX_VERTEX_STREAMS);
+      break;
+   default:
+      set_predicate_for_occlusion_query(brw, query);
+   }
 
    if (inverted)
       load_op = MI_PREDICATE_LOADOP_LOAD;
@@ -102,6 +129,11 @@ brw_begin_conditional_render(struct gl_context *ctx,
    if (!brw->predicate.supported)
       return;
 
+   if ((query->Base.Target == GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB ||
+        query->Base.Target == GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB) &&
+       !can_do_mi_math_and_lrr(brw->screen))
+      return;
+
    switch (mode) {
    case GL_QUERY_WAIT:
    case GL_QUERY_NO_WAIT:
@@ -151,13 +183,20 @@ brw_init_conditional_render_functions(struct dd_function_table *functions)
 bool
 brw_check_conditional_render(struct brw_context *brw)
 {
-   if (brw->predicate.supported) {
+   const struct gl_query_object *query = brw->ctx.Query.CondRenderQuery;
+
+   const bool query_is_xfb = query &&
+      (query->Target == GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB ||
+       query->Target == GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB);
+
+   if (brw->predicate.supported &&
+       (can_do_mi_math_and_lrr(brw->screen) || !query_is_xfb)) {
       /* 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) {
+   } else if (query) {
       perf_debug("Conditional rendering is implemented in software and may "
                  "stall.\n");
       return _mesa_check_conditional_render(&brw->ctx);