i965: Use brw_wm_prog_data::uses_kill, not gl_fragment_program::UsesKill
[mesa.git] / src / mesa / drivers / dri / i965 / gen7_gs_state.c
index 3dd5896eee8dd3811cc7b5ecab415d45aa78ccba..4fe1354262e51de349a3c9e7166d3a84d171a22a 100644 (file)
 #include "brw_defines.h"
 #include "intel_batchbuffer.h"
 
-
-static void
-gen7_upload_gs_push_constants(struct brw_context *brw)
-{
-   /* BRW_NEW_GEOMETRY_PROGRAM */
-   const struct brw_geometry_program *vp =
-      (struct brw_geometry_program *) brw->geometry_program;
-   if (!vp)
-      return;
-
-   /* CACHE_NEW_GS_PROG */
-   const struct brw_vec4_prog_data *prog_data = &brw->gs.prog_data->base;
-   struct brw_stage_state *stage_state = &brw->gs.base;
-
-   gen6_upload_vec4_push_constants(brw, &vp->program.Base, prog_data,
-                                   stage_state, AUB_TRACE_VS_CONSTANTS);
-}
-
-const struct brw_tracked_state gen7_gs_push_constants = {
-   .dirty = {
-      .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
-      .brw   = (BRW_NEW_BATCH |
-               BRW_NEW_GEOMETRY_PROGRAM),
-      .cache = CACHE_NEW_GS_PROG,
-   },
-   .emit = gen7_upload_gs_push_constants,
-};
-
-
 static void
 upload_gs_state(struct brw_context *brw)
 {
@@ -66,31 +37,34 @@ upload_gs_state(struct brw_context *brw)
    /* CACHE_NEW_GS_PROG */
    const struct brw_vec4_prog_data *prog_data = &brw->gs.prog_data->base;
 
-   /* BRW_NEW_GS_BINDING_TABLE */
-   BEGIN_BATCH(2);
-   OUT_BATCH(_3DSTATE_BINDING_TABLE_POINTERS_GS << 16 | (2 - 2));
-   OUT_BATCH(stage_state->bind_bo_offset);
-   ADVANCE_BATCH();
-
-   /* CACHE_NEW_SAMPLER */
-   BEGIN_BATCH(2);
-   OUT_BATCH(_3DSTATE_SAMPLER_STATE_POINTERS_GS << 16 | (2 - 2));
-   OUT_BATCH(stage_state->sampler_offset);
-   ADVANCE_BATCH();
-
-   gen7_upload_constant_state(brw, stage_state, active, _3DSTATE_CONSTANT_GS);
+   /**
+    * From Graphics BSpec: 3D-Media-GPGPU Engine > 3D Pipeline Stages >
+    * Geometry > Geometry Shader > State:
+    *
+    *     "Note: Because of corruption in IVB:GT2, software needs to flush the
+    *     whole fixed function pipeline when the GS enable changes value in
+    *     the 3DSTATE_GS."
+    *
+    * The hardware architects have clarified that in this context "flush the
+    * whole fixed function pipeline" means to emit a PIPE_CONTROL with the "CS
+    * Stall" bit set.
+    */
+   if (!brw->is_haswell && brw->gt == 2 && brw->gs.enabled != active)
+      gen7_emit_cs_stall_flush(brw);
 
    if (active) {
       BEGIN_BATCH(7);
       OUT_BATCH(_3DSTATE_GS << 16 | (7 - 2));
       OUT_BATCH(stage_state->prog_offset);
       OUT_BATCH(((ALIGN(stage_state->sampler_count, 4)/4) <<
-                 GEN6_GS_SAMPLER_COUNT_SHIFT));
+                 GEN6_GS_SAMPLER_COUNT_SHIFT) |
+                ((brw->gs.prog_data->base.base.binding_table.size_bytes / 4) <<
+                 GEN6_GS_BINDING_TABLE_ENTRY_COUNT_SHIFT));
 
-      if (brw->gs.prog_data->base.total_scratch) {
+      if (brw->gs.prog_data->base.base.total_scratch) {
          OUT_RELOC(stage_state->scratch_bo,
                    I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
-                   ffs(brw->gs.prog_data->base.total_scratch) - 11);
+                   ffs(brw->gs.prog_data->base.base.total_scratch) - 11);
       } else {
          OUT_BATCH(0);
       }
@@ -103,16 +77,46 @@ upload_gs_state(struct brw_context *brw)
          (prog_data->urb_read_length <<
           GEN6_GS_URB_READ_LENGTH_SHIFT) |
          (0 << GEN6_GS_URB_ENTRY_READ_OFFSET_SHIFT) |
-         (prog_data->dispatch_grf_start_reg <<
+         (prog_data->base.dispatch_grf_start_reg <<
           GEN6_GS_DISPATCH_START_GRF_SHIFT);
+
+      /* Note: the meaning of the GEN7_GS_REORDER_TRAILING bit changes between
+       * Ivy Bridge and Haswell.
+       *
+       * On Ivy Bridge, setting this bit causes the vertices of a triangle
+       * strip to be delivered to the geometry shader in an order that does
+       * not strictly follow the OpenGL spec, but preserves triangle
+       * orientation.  For example, if the vertices are (1, 2, 3, 4, 5), then
+       * the geometry shader sees triangles:
+       *
+       * (1, 2, 3), (2, 4, 3), (3, 4, 5)
+       *
+       * (Clearing the bit is even worse, because it fails to preserve
+       * orientation).
+       *
+       * Triangle strips with adjacency always ordered in a way that preserves
+       * triangle orientation but does not strictly follow the OpenGL spec,
+       * regardless of the setting of this bit.
+       *
+       * On Haswell, both triangle strips and triangle strips with adjacency
+       * are always ordered in a way that preserves triangle orientation.
+       * Setting this bit causes the ordering to strictly follow the OpenGL
+       * spec.
+       *
+       * So in either case we want to set the bit.  Unfortunately on Ivy
+       * Bridge this will get the order close to correct but not perfect.
+       */
       uint32_t dw5 =
          ((brw->max_gs_threads - 1) << max_threads_shift) |
          (brw->gs.prog_data->control_data_header_size_hwords <<
           GEN7_GS_CONTROL_DATA_HEADER_SIZE_SHIFT) |
-         GEN7_GS_DISPATCH_MODE_DUAL_OBJECT |
+         ((brw->gs.prog_data->invocations - 1) <<
+          GEN7_GS_INSTANCE_CONTROL_SHIFT) |
+         brw->gs.prog_data->dispatch_mode |
          GEN6_GS_STATISTICS_ENABLE |
          (brw->gs.prog_data->include_primitive_id ?
           GEN7_GS_INCLUDE_PRIMITIVE_ID : 0) |
+         GEN7_GS_REORDER_TRAILING |
          GEN7_GS_ENABLE;
       uint32_t dw6 = 0;
 
@@ -144,17 +148,16 @@ upload_gs_state(struct brw_context *brw)
       OUT_BATCH(0);
       ADVANCE_BATCH();
    }
+   brw->gs.enabled = active;
 }
 
 const struct brw_tracked_state gen7_gs_state = {
    .dirty = {
-      .mesa  = _NEW_TRANSFORM | _NEW_PROGRAM_CONSTANTS,
+      .mesa  = _NEW_TRANSFORM,
       .brw   = (BRW_NEW_CONTEXT |
                 BRW_NEW_GEOMETRY_PROGRAM |
-                BRW_NEW_GS_BINDING_TABLE |
-                BRW_NEW_BATCH |
-                BRW_NEW_PUSH_CONSTANT_ALLOCATION),
-      .cache = CACHE_NEW_GS_PROG | CACHE_NEW_SAMPLER
+                BRW_NEW_BATCH),
+      .cache = CACHE_NEW_GS_PROG
    },
    .emit = upload_gs_state,
 };