Merge commit 'origin/st-shader-varients'
[mesa.git] / src / mesa / drivers / dri / i965 / brw_urb.c
index cf805cef2886287532ef724500bcc671da07f0fe..8c6f4355a6eccd1bede10b814e48a4886df1694c 100644 (file)
 #define SF 3
 #define CS 4
 
-/* XXX: Are the min_entry_size numbers useful?
+/** @file brw_urb.c
+ *
+ * Manages the division of the URB space between the various fixed-function
+ * units.
+ *
+ * See the Thread Initiation Management section of the GEN4 B-Spec, and
+ * the individual *_STATE structures for restrictions on numbers of
+ * entries and threads.
+ */
+
+/*
+ * Generally, a unit requires a min_nr_entries based on how many entries
+ * it produces before the downstream unit gets unblocked and can use and
+ * dereference some of its handles.
+ *
+ * The SF unit preallocates a PUE at the start of thread dispatch, and only
+ * uses that one.  So it requires one entry per thread.
+ *
+ * For CLIP, the SF unit will hold the previous primitive while the
+ * next is getting assembled, meaning that linestrips require 3 CLIP VUEs
+ * (vertices) to ensure continued processing, trifans require 4, and tristrips
+ * require 5.  There can be 1 or 2 threads, and each has the same requirement.
+ *
+ * GS has the same requirement as CLIP, but it never handles tristrips,
+ * so we can lower the minimum to 4 for the POLYGONs (trifans) it produces.
+ * We only run it single-threaded.
+ *
+ * For VS, the number of entries may be 8, 12, 16, or 32 (or 64 on G4X).
+ * Each thread processes 2 preallocated VUEs (vertices) at a time, and they
+ * get streamed down as soon as threads processing earlier vertices get
+ * theirs accepted.
+ *
+ * Each unit will take the number of URB entries we give it (based on the
+ * entry size calculated in brw_vs_emit.c for VUEs, brw_sf_emit.c for PUEs,
+ * and brw_curbe.c for the CURBEs) and decide its maximum number of
+ * threads it can support based on that. in brw_*_state.c.
+ *
+ * XXX: Are the min_entry_size numbers useful?
  * XXX: Verify min_nr_entries, esp for VS.
  * XXX: Verify SF min_entry_size.
  */
@@ -52,9 +89,9 @@ static const struct {
    GLuint min_entry_size;
    GLuint max_entry_size;
 } limits[CS+1] = {
-   { 8, 32, 1, 5 },                    /* vs */
+   { 16, 32, 1, 5 },                   /* vs */
    { 4, 8,  1, 5 },                    /* gs */
-   { 6, 8,  1, 5 },                    /* clp */
+   { 5, 10,  1, 5 },                   /* clp */
    { 1, 8,  1, 12 },                   /* sf */
    { 1, 4,  1, 32 }                    /* cs */
 };
@@ -92,9 +129,9 @@ static void recalculate_urb_fence( struct brw_context *brw )
    if (brw->urb.vsize < vsize ||
        brw->urb.sfsize < sfsize ||
        brw->urb.csize < csize ||
-       (brw->urb.constrained && (brw->urb.vsize > brw->urb.vsize ||
-                                brw->urb.sfsize > brw->urb.sfsize ||
-                                brw->urb.csize > brw->urb.csize))) {
+       (brw->urb.constrained && (brw->urb.vsize > vsize ||
+                                brw->urb.sfsize > sfsize ||
+                                brw->urb.csize > csize))) {
       
 
       brw->urb.csize = csize;
@@ -106,7 +143,29 @@ static void recalculate_urb_fence( struct brw_context *brw )
       brw->urb.nr_clip_entries = limits[CLP].preferred_nr_entries;
       brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;        
       brw->urb.nr_cs_entries = limits[CS].preferred_nr_entries;        
-      
+
+      brw->urb.constrained = 0;
+
+      if (BRW_IS_IGDNG(brw)) {
+         brw->urb.nr_vs_entries = 128;
+         brw->urb.nr_sf_entries = 48;
+         if (check_urb_layout(brw)) {
+            goto done;
+         } else {
+            brw->urb.constrained = 1;
+            brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
+            brw->urb.nr_sf_entries = limits[SF].preferred_nr_entries;
+         }
+      } else if (BRW_IS_G4X(brw)) {
+        brw->urb.nr_vs_entries = 64;
+        if (check_urb_layout(brw)) {
+           goto done;
+        } else {
+           brw->urb.constrained = 1;
+           brw->urb.nr_vs_entries = limits[VS].preferred_nr_entries;
+        }
+      }
+
       if (!check_urb_layout(brw)) {
         brw->urb.nr_vs_entries = limits[VS].min_nr_entries;    
         brw->urb.nr_gs_entries = limits[GS].min_nr_entries;    
@@ -114,6 +173,10 @@ static void recalculate_urb_fence( struct brw_context *brw )
         brw->urb.nr_sf_entries = limits[SF].min_nr_entries;    
         brw->urb.nr_cs_entries = limits[CS].min_nr_entries;    
 
+        /* Mark us as operating with constrained nr_entries, so that next
+         * time we recalculate we'll resize the fences in the hope of
+         * escaping constrained mode and getting back to normal performance.
+         */
         brw->urb.constrained = 1;
         
         if (!check_urb_layout(brw)) {
@@ -128,9 +191,8 @@ static void recalculate_urb_fence( struct brw_context *brw )
         if (INTEL_DEBUG & (DEBUG_URB|DEBUG_FALLBACKS))
            _mesa_printf("URB CONSTRAINED\n");
       }
-      else 
-        brw->urb.constrained = 0;
 
+done:
       if (INTEL_DEBUG & DEBUG_URB)
         _mesa_printf("URB fence: %d ..VS.. %d ..GS.. %d ..CLP.. %d ..SF.. %d ..CS.. %d\n",
                      brw->urb.vs_start,
@@ -152,7 +214,7 @@ const struct brw_tracked_state brw_recalculate_urb_fence = {
       .cache = (CACHE_NEW_VS_PROG |
                CACHE_NEW_SF_PROG)
    },
-   .update = recalculate_urb_fence
+   .prepare = recalculate_urb_fence
 };
 
 
@@ -186,15 +248,3 @@ void brw_upload_urb_fence(struct brw_context *brw)
 
    BRW_BATCH_STRUCT(brw, &uf);
 }
-
-
-#if 0
-const struct brw_tracked_state brw_urb_fence = {
-   .dirty = {
-      .mesa = 0,
-      .brw = BRW_NEW_URB_FENCE | BRW_NEW_PSP,
-      .cache = 0
-   },
-   .update = brw_upload_urb_fence
-};
-#endif