i965/gs: If a DUAL_OBJECT gs would spill, fall back to DUAL_INSTANCED.
authorPaul Berry <stereotype441@gmail.com>
Wed, 16 Oct 2013 19:27:37 +0000 (12:27 -0700)
committerPaul Berry <stereotype441@gmail.com>
Fri, 25 Oct 2013 05:00:53 +0000 (22:00 -0700)
This is similar to what we do for 16-wide vs 8-wide fragment shaders.
First we try compiling the geometry shader in DUAL_OBJECT mode.  If we
can't do that without spilling, we fall back on DUAL_INSTANCED mode,
which should require less spilling (since it uses an interleaved
layout of payload registers).

In an ideal world we'd fall back to SINGLE mode, which would allow us
to interleave general-purpose registers too (resulting in even less
likelihood of spilling).  But at the moment, the vec4 generator and
visitor classes don't have the infrastructure to interleave general
purpose registers, so DUAL_INSTANCED is the best we can do.

As a side benefit this paves the way for implementing instanced
geometry shaders (which are incompatible with DUAL_OBJECT mode).

Since most geometry shaders used in piglit testing are small,
DUAL_INSTANCED mode won't get exercised very much in a normal piglit
run.  To force DUAL_INSTANCED mode to be used for all geometry
shaders, set INTEL_DEBUG=nodualobj.

Reviewed-by: Eric Anholt <eric@anholt.net>
src/mesa/drivers/dri/i965/brw_vec4_gs_visitor.cpp
src/mesa/drivers/dri/i965/intel_debug.c
src/mesa/drivers/dri/i965/intel_debug.h

index b135f616ae1c6323dd615e5fb2a950ccb34956fe..adbb1cf094517660add8a43e92bfde9c24b9b790 100644 (file)
@@ -550,8 +550,34 @@ brw_gs_emit(struct brw_context *brw,
       printf("\n\n");
    }
 
-   /* Assume the geometry shader will use DUAL_OBJECT dispatch for now. */
-   c->prog_data.dual_instanced_dispatch = false;
+   /* Compile the geometry shader in DUAL_OBJECT dispatch mode, if we can do
+    * so without spilling.
+    */
+   if (likely(!(INTEL_DEBUG & DEBUG_NO_DUAL_OBJECT_GS))) {
+      c->prog_data.dual_instanced_dispatch = false;
+
+      vec4_gs_visitor v(brw, c, prog, shader, mem_ctx, true /* no_spills */);
+      if (v.run()) {
+         vec4_generator g(brw, prog, &c->gp->program.Base, &c->prog_data.base,
+                          mem_ctx, INTEL_DEBUG & DEBUG_GS);
+         const unsigned *generated =
+            g.generate_assembly(&v.instructions, final_assembly_size);
+
+         return generated;
+      }
+   }
+
+   /* Either we failed to compile in DUAL_OBJECT mode (probably because it
+    * would have required spilling) or DUAL_OBJECT mode is disabled.  So fall
+    * back to DUAL_INSTANCED mode, which consumes fewer registers.
+    *
+    * FIXME: In an ideal world we'd fall back to SINGLE mode, which would
+    * allow us to interleave general purpose registers (resulting in even less
+    * likelihood of spilling).  But at the moment, the vec4 generator and
+    * visitor classes don't have the infrastructure to interleave general
+    * purpose registers, so DUAL_INSTANCED is the best we can do.
+    */
+   c->prog_data.dual_instanced_dispatch = true;
 
    vec4_gs_visitor v(brw, c, prog, shader, mem_ctx, false /* no_spills */);
    if (!v.run()) {
index 03abdfa8612a44514d4f080214b977cfbab2fff0..b3e29353c4cf3b416c6254ddb2c7b16caf1f9e9f 100644 (file)
@@ -64,6 +64,7 @@ static const struct dri_debug_control debug_control[] = {
    { "shader_time", DEBUG_SHADER_TIME },
    { "no16",  DEBUG_NO16 },
    { "blorp", DEBUG_BLORP },
+   { "nodualobj", DEBUG_NO_DUAL_OBJECT_GS },
    { NULL,    0 }
 };
 
index 486a8d650caf89decb011ef6a093fc1d19029a6c..718d95b1da5fbe67803e2958565514a13d03d886 100644 (file)
@@ -60,6 +60,7 @@ extern int INTEL_DEBUG;
 #define DEBUG_BLORP       0x10000000
 #define DEBUG_NO16        0x20000000
 #define DEBUG_VUE         0x40000000
+#define DEBUG_NO_DUAL_OBJECT_GS 0x80000000
 
 #ifdef HAVE_ANDROID_PLATFORM
 #define LOG_TAG "INTEL-MESA"