i965/gs: Add a case to brwNewProgram() for geometry shaders.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_gs.c
index 886bf98fb85a5e2a52d4a2fd3614f93e3b7d51f8..bd32db1e4f1cd77bf4399a891b02a1127481ff51 100644 (file)
@@ -32,6 +32,7 @@
 #include "main/glheader.h"
 #include "main/macros.h"
 #include "main/enums.h"
+#include "main/transformfeedback.h"
 
 #include "intel_batchbuffer.h"
 
@@ -47,7 +48,6 @@
 static void compile_gs_prog( struct brw_context *brw,
                             struct brw_gs_prog_key *key )
 {
-   struct intel_context *intel = &brw->intel;
    struct brw_gs_compile c;
    const GLuint *program;
    void *mem_ctx;
@@ -56,11 +56,10 @@ static void compile_gs_prog( struct brw_context *brw,
    memset(&c, 0, sizeof(c));
    
    c.key = *key;
-   /* The geometry shader needs to access the entire VUE. */
-   brw_compute_vue_map(&c.vue_map, intel, c.key.userclip_active, c.key.attrs);
+   c.vue_map = brw->vs.prog_data->base.vue_map;
    c.nr_regs = (c.vue_map.num_slots + 1)/2;
 
-   mem_ctx = NULL;
+   mem_ctx = ralloc_context(NULL);
    
    /* Begin the compilation:
     */
@@ -73,7 +72,7 @@ static void compile_gs_prog( struct brw_context *brw,
     */
    brw_set_mask_control(&c.func, BRW_MASK_DISABLE);
 
-   if (intel->gen >= 6) {
+   if (brw->gen >= 6) {
       unsigned num_verts;
       bool check_edge_flag;
       /* On Sandybridge, we use the GS for implementing transform feedback
@@ -139,7 +138,7 @@ static void compile_gs_prog( struct brw_context *brw,
       printf("gs:\n");
       for (i = 0; i < program_size / sizeof(struct brw_instruction); i++)
         brw_disasm(stdout, &((struct brw_instruction *)program)[i],
-                   intel->gen);
+                   brw->gen);
       printf("\n");
     }
 
@@ -154,13 +153,19 @@ static void compile_gs_prog( struct brw_context *brw,
 static void populate_key( struct brw_context *brw,
                          struct brw_gs_prog_key *key )
 {
-   struct gl_context *ctx = &brw->intel.ctx;
-   struct intel_context *intel = &brw->intel;
+   static const unsigned swizzle_for_offset[4] = {
+      BRW_SWIZZLE4(0, 1, 2, 3),
+      BRW_SWIZZLE4(1, 2, 3, 3),
+      BRW_SWIZZLE4(2, 3, 3, 3),
+      BRW_SWIZZLE4(3, 3, 3, 3)
+   };
+
+   struct gl_context *ctx = &brw->ctx;
 
    memset(key, 0, sizeof(*key));
 
-   /* CACHE_NEW_VS_PROG */
-   key->attrs = brw->vs.prog_data->outputs_written;
+   /* CACHE_NEW_VS_PROG (part of VUE map) */
+   key->attrs = brw->vs.prog_data->base.vue_map.slots_valid;
 
    /* BRW_NEW_PRIMITIVE */
    key->primitive = brw->primitive;
@@ -174,16 +179,13 @@ static void populate_key( struct brw_context *brw,
       key->pv_first = true;
    }
 
-   /* _NEW_TRANSFORM */
-   key->userclip_active = (ctx->Transform.ClipPlanesEnabled != 0);
-
-   if (intel->gen >= 7) {
+   if (brw->gen >= 7) {
       /* On Gen7 and later, we don't use GS (yet). */
       key->need_gs_prog = false;
-   } else if (intel->gen == 6) {
+   } else if (brw->gen == 6) {
       /* On Gen6, GS is used for transform feedback. */
-      /* _NEW_TRANSFORM_FEEDBACK */
-      if (ctx->TransformFeedback.CurrentObject->Active) {
+      /* BRW_NEW_TRANSFORM_FEEDBACK */
+      if (_mesa_is_xfb_active_and_unpaused(ctx)) {
          const struct gl_shader_program *shaderprog =
             ctx->Shader.CurrentVertexProgram;
          const struct gl_transform_feedback_info *linked_xfb_info =
@@ -193,7 +195,7 @@ static void populate_key( struct brw_context *brw,
          /* Make sure that the VUE slots won't overflow the unsigned chars in
           * key->transform_feedback_bindings[].
           */
-         STATIC_ASSERT(BRW_VERT_RESULT_MAX <= 256);
+         STATIC_ASSERT(BRW_VARYING_SLOT_COUNT <= 256);
 
          /* Make sure that we don't need more binding table entries than we've
           * set aside for use in transform feedback.  (We shouldn't, since we
@@ -206,14 +208,10 @@ static void populate_key( struct brw_context *brw,
          for (i = 0; i < key->num_transform_feedback_bindings; ++i) {
             key->transform_feedback_bindings[i] =
                linked_xfb_info->Outputs[i].OutputRegister;
+            key->transform_feedback_swizzles[i] =
+               swizzle_for_offset[linked_xfb_info->Outputs[i].ComponentOffset];
          }
       }
-      /* On Gen6, GS is also used for rasterizer discard. */
-      /* _NEW_RASTERIZER_DISCARD */
-      if (ctx->RasterDiscard) {
-         key->need_gs_prog = true;
-         key->rasterizer_discard = true;
-      }
    } else {
       /* Pre-gen6, GS is used to transform QUADLIST, QUADSTRIP, and LINELOOP
        * into simpler primitives.
@@ -222,11 +220,6 @@ static void populate_key( struct brw_context *brw,
                            brw->primitive == _3DPRIM_QUADSTRIP ||
                            brw->primitive == _3DPRIM_LINELOOP);
    }
-   /* For testing, the environment variable INTEL_FORCE_GS can be used to
-    * force a GS program to be used, even if it's not necessary.
-    */
-   if (getenv("INTEL_FORCE_GS"))
-      key->need_gs_prog = true;
 }
 
 /* Calculate interpolants for triangle and line rasterization.
@@ -256,11 +249,9 @@ brw_upload_gs_prog(struct brw_context *brw)
 
 const struct brw_tracked_state brw_gs_prog = {
    .dirty = {
-      .mesa  = (_NEW_LIGHT |
-                _NEW_TRANSFORM |
-                _NEW_TRANSFORM_FEEDBACK |
-                _NEW_RASTERIZER_DISCARD),
-      .brw   = BRW_NEW_PRIMITIVE,
+      .mesa  = (_NEW_LIGHT),
+      .brw   = (BRW_NEW_PRIMITIVE |
+                BRW_NEW_TRANSFORM_FEEDBACK),
       .cache = CACHE_NEW_VS_PROG
    },
    .emit = brw_upload_gs_prog