~ubuntu-branches/ubuntu/precise/mesa-lts-quantal/precise-updates

« back to all changes in this revision

Viewing changes to src/mesa/drivers/dri/i965/brw_gs_emit.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 20:58:34 UTC
  • Revision ID: package-import@ubuntu.com-20121130205834-gazuvne3fpwlf012
Tags: upstream-9.0
Import upstream version 9.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 Copyright (C) Intel Corp.  2006.  All Rights Reserved.
 
3
 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
 
4
 develop this 3D driver.
 
5
 
 
6
 Permission is hereby granted, free of charge, to any person obtaining
 
7
 a copy of this software and associated documentation files (the
 
8
 "Software"), to deal in the Software without restriction, including
 
9
 without limitation the rights to use, copy, modify, merge, publish,
 
10
 distribute, sublicense, and/or sell copies of the Software, and to
 
11
 permit persons to whom the Software is furnished to do so, subject to
 
12
 the following conditions:
 
13
 
 
14
 The above copyright notice and this permission notice (including the
 
15
 next paragraph) shall be included in all copies or substantial
 
16
 portions of the Software.
 
17
 
 
18
 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
19
 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
20
 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 
21
 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
 
22
 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 
23
 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 
24
 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
25
 
 
26
 **********************************************************************/
 
27
 /*
 
28
  * Authors:
 
29
  *   Keith Whitwell <keith@tungstengraphics.com>
 
30
  */
 
31
 
 
32
 
 
33
#include "main/glheader.h"
 
34
#include "main/macros.h"
 
35
#include "main/enums.h"
 
36
 
 
37
#include "program/program.h"
 
38
#include "intel_batchbuffer.h"
 
39
 
 
40
#include "brw_defines.h"
 
41
#include "brw_context.h"
 
42
#include "brw_eu.h"
 
43
#include "brw_gs.h"
 
44
 
 
45
/**
 
46
 * Allocate registers for GS.
 
47
 *
 
48
 * If sol_program is true, then:
 
49
 *
 
50
 * - The thread will be spawned with the "SVBI Payload Enable" bit set, so GRF
 
51
 *   1 needs to be set aside to hold the streamed vertex buffer indices.
 
52
 *
 
53
 * - The thread will need to use the destination_indices register.
 
54
 */
 
55
static void brw_gs_alloc_regs( struct brw_gs_compile *c,
 
56
                               GLuint nr_verts,
 
57
                               bool sol_program )
 
58
{
 
59
   GLuint i = 0,j;
 
60
 
 
61
   /* Register usage is static, precompute here:
 
62
    */
 
63
   c->reg.R0 = retype(brw_vec8_grf(i, 0), BRW_REGISTER_TYPE_UD); i++;
 
64
 
 
65
   /* Streamed vertex buffer indices */
 
66
   if (sol_program)
 
67
      c->reg.SVBI = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD);
 
68
 
 
69
   /* Payload vertices plus space for more generated vertices:
 
70
    */
 
71
   for (j = 0; j < nr_verts; j++) {
 
72
      c->reg.vertex[j] = brw_vec4_grf(i, 0);
 
73
      i += c->nr_regs;
 
74
   }
 
75
 
 
76
   c->reg.header = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD);
 
77
   c->reg.temp = retype(brw_vec8_grf(i++, 0), BRW_REGISTER_TYPE_UD);
 
78
 
 
79
   if (sol_program) {
 
80
      c->reg.destination_indices =
 
81
         retype(brw_vec4_grf(i++, 0), BRW_REGISTER_TYPE_UD);
 
82
   }
 
83
 
 
84
   c->prog_data.urb_read_length = c->nr_regs; 
 
85
   c->prog_data.total_grf = i;
 
86
}
 
87
 
 
88
 
 
89
/**
 
90
 * Set up the initial value of c->reg.header register based on c->reg.R0.
 
91
 *
 
92
 * The following information is passed to the GS thread in R0, and needs to be
 
93
 * included in the first URB_WRITE or FF_SYNC message sent by the GS:
 
94
 *
 
95
 * - DWORD 0 [31:0] handle info (Gen4 only)
 
96
 * - DWORD 5 [7:0] FFTID
 
97
 * - DWORD 6 [31:0] Debug info
 
98
 * - DWORD 7 [31:0] Debug info
 
99
 *
 
100
 * This function sets up the above data by copying by copying the contents of
 
101
 * R0 to the header register.
 
102
 */
 
103
static void brw_gs_initialize_header(struct brw_gs_compile *c)
 
104
{
 
105
   struct brw_compile *p = &c->func;
 
106
   brw_MOV(p, c->reg.header, c->reg.R0);
 
107
}
 
108
 
 
109
/**
 
110
 * Overwrite DWORD 2 of c->reg.header with the given immediate unsigned value.
 
111
 *
 
112
 * In URB_WRITE messages, DWORD 2 contains the fields PrimType, PrimStart,
 
113
 * PrimEnd, Increment CL_INVOCATIONS, and SONumPrimsWritten, many of which we
 
114
 * need to be able to update on a per-vertex basis.
 
115
 */
 
116
static void brw_gs_overwrite_header_dw2(struct brw_gs_compile *c,
 
117
                                        unsigned dw2)
 
118
{
 
119
   struct brw_compile *p = &c->func;
 
120
   brw_MOV(p, get_element_ud(c->reg.header, 2), brw_imm_ud(dw2));
 
121
}
 
122
 
 
123
/**
 
124
 * Overwrite DWORD 2 of c->reg.header with the primitive type from c->reg.R0.
 
125
 *
 
126
 * When the thread is spawned, GRF 0 contains the primitive type in bits 4:0
 
127
 * of DWORD 2.  URB_WRITE messages need the primitive type in bits 6:2 of
 
128
 * DWORD 2.  So this function extracts the primitive type field, bitshifts it
 
129
 * appropriately, and stores it in c->reg.header.
 
130
 */
 
131
static void brw_gs_overwrite_header_dw2_from_r0(struct brw_gs_compile *c)
 
132
{
 
133
   struct brw_compile *p = &c->func;
 
134
   brw_AND(p, get_element_ud(c->reg.header, 2), get_element_ud(c->reg.R0, 2),
 
135
           brw_imm_ud(0x1f));
 
136
   brw_SHL(p, get_element_ud(c->reg.header, 2),
 
137
           get_element_ud(c->reg.header, 2), brw_imm_ud(2));
 
138
}
 
139
 
 
140
/**
 
141
 * Apply an additive offset to DWORD 2 of c->reg.header.
 
142
 *
 
143
 * This is used to set/unset the "PrimStart" and "PrimEnd" flags appropriately
 
144
 * for each vertex.
 
145
 */
 
146
static void brw_gs_offset_header_dw2(struct brw_gs_compile *c, int offset)
 
147
{
 
148
   struct brw_compile *p = &c->func;
 
149
   brw_ADD(p, get_element_d(c->reg.header, 2), get_element_d(c->reg.header, 2),
 
150
           brw_imm_d(offset));
 
151
}
 
152
 
 
153
 
 
154
/**
 
155
 * Emit a vertex using the URB_WRITE message.  Use the contents of
 
156
 * c->reg.header for the message header, and the registers starting at \c vert
 
157
 * for the vertex data.
 
158
 *
 
159
 * If \c last is true, then this is the last vertex, so no further URB space
 
160
 * should be allocated, and this message should end the thread.
 
161
 *
 
162
 * If \c last is false, then a new URB entry will be allocated, and its handle
 
163
 * will be stored in DWORD 0 of c->reg.header for use in the next URB_WRITE
 
164
 * message.
 
165
 */
 
166
static void brw_gs_emit_vue(struct brw_gs_compile *c, 
 
167
                            struct brw_reg vert,
 
168
                            bool last)
 
169
{
 
170
   struct brw_compile *p = &c->func;
 
171
   bool allocate = !last;
 
172
 
 
173
   /* Copy the vertex from vertn into m1..mN+1:
 
174
    */
 
175
   brw_copy8(p, brw_message_reg(1), vert, c->nr_regs);
 
176
 
 
177
   /* Send each vertex as a seperate write to the urb.  This is
 
178
    * different to the concept in brw_sf_emit.c, where subsequent
 
179
    * writes are used to build up a single urb entry.  Each of these
 
180
    * writes instantiates a seperate urb entry, and a new one must be
 
181
    * allocated each time.
 
182
    */
 
183
   brw_urb_WRITE(p, 
 
184
                 allocate ? c->reg.temp
 
185
                          : retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
 
186
                 0,
 
187
                 c->reg.header,
 
188
                 allocate,
 
189
                 1,             /* used */
 
190
                 c->nr_regs + 1, /* msg length */
 
191
                 allocate ? 1 : 0, /* response length */
 
192
                 allocate ? 0 : 1, /* eot */
 
193
                 1,             /* writes_complete */
 
194
                 0,             /* urb offset */
 
195
                 BRW_URB_SWIZZLE_NONE);
 
196
 
 
197
   if (allocate) {
 
198
      brw_MOV(p, get_element_ud(c->reg.header, 0),
 
199
              get_element_ud(c->reg.temp, 0));
 
200
   }
 
201
}
 
202
 
 
203
/**
 
204
 * De-allocate the URB entry that was previously allocated to this thread
 
205
 * (without writing any vertex data to it), and terminate the thread.  This is
 
206
 * used to implement RASTERIZER_DISCARD functionality.
 
207
 */
 
208
static void brw_gs_terminate(struct brw_gs_compile *c)
 
209
{
 
210
   struct brw_compile *p = &c->func;
 
211
   brw_urb_WRITE(p,
 
212
                 retype(brw_null_reg(), BRW_REGISTER_TYPE_UD), /* dest */
 
213
                 0, /* msg_reg_nr */
 
214
                 c->reg.header, /* src0 */
 
215
                 false, /* allocate */
 
216
                 false, /* used */
 
217
                 1, /* msg_length */
 
218
                 0, /* response_length */
 
219
                 true, /* eot */
 
220
                 true, /* writes_complete */
 
221
                 0, /* offset */
 
222
                 BRW_URB_SWIZZLE_NONE);
 
223
}
 
224
 
 
225
/**
 
226
 * Send an FF_SYNC message to ensure that all previously spawned GS threads
 
227
 * have finished sending primitives down the pipeline, and to allocate a URB
 
228
 * entry for the first output vertex.  Only needed when intel->needs_ff_sync
 
229
 * is true.
 
230
 *
 
231
 * This function modifies c->reg.header: in DWORD 1, it stores num_prim (which
 
232
 * is needed by the FF_SYNC message), and in DWORD 0, it stores the handle to
 
233
 * the allocated URB entry (which will be needed by the URB_WRITE meesage that
 
234
 * follows).
 
235
 */
 
236
static void brw_gs_ff_sync(struct brw_gs_compile *c, int num_prim)
 
237
{
 
238
   struct brw_compile *p = &c->func;
 
239
 
 
240
   brw_MOV(p, get_element_ud(c->reg.header, 1), brw_imm_ud(num_prim));
 
241
   brw_ff_sync(p,
 
242
               c->reg.temp,
 
243
               0,
 
244
               c->reg.header,
 
245
               1, /* allocate */
 
246
               1, /* response length */
 
247
               0 /* eot */);
 
248
   brw_MOV(p, get_element_ud(c->reg.header, 0),
 
249
           get_element_ud(c->reg.temp, 0));
 
250
}
 
251
 
 
252
 
 
253
void brw_gs_quads( struct brw_gs_compile *c, struct brw_gs_prog_key *key )
 
254
{
 
255
   struct intel_context *intel = &c->func.brw->intel;
 
256
 
 
257
   brw_gs_alloc_regs(c, 4, false);
 
258
   brw_gs_initialize_header(c);
 
259
   /* Use polygons for correct edgeflag behaviour. Note that vertex 3
 
260
    * is the PV for quads, but vertex 0 for polygons:
 
261
    */
 
262
   if (intel->needs_ff_sync)
 
263
      brw_gs_ff_sync(c, 1);
 
264
   brw_gs_overwrite_header_dw2(
 
265
      c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
 
266
          | URB_WRITE_PRIM_START));
 
267
   if (key->pv_first) {
 
268
      brw_gs_emit_vue(c, c->reg.vertex[0], 0);
 
269
      brw_gs_overwrite_header_dw2(
 
270
         c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
 
271
      brw_gs_emit_vue(c, c->reg.vertex[1], 0);
 
272
      brw_gs_emit_vue(c, c->reg.vertex[2], 0);
 
273
      brw_gs_overwrite_header_dw2(
 
274
         c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
 
275
             | URB_WRITE_PRIM_END));
 
276
      brw_gs_emit_vue(c, c->reg.vertex[3], 1);
 
277
   }
 
278
   else {
 
279
      brw_gs_emit_vue(c, c->reg.vertex[3], 0);
 
280
      brw_gs_overwrite_header_dw2(
 
281
         c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
 
282
      brw_gs_emit_vue(c, c->reg.vertex[0], 0);
 
283
      brw_gs_emit_vue(c, c->reg.vertex[1], 0);
 
284
      brw_gs_overwrite_header_dw2(
 
285
         c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
 
286
             | URB_WRITE_PRIM_END));
 
287
      brw_gs_emit_vue(c, c->reg.vertex[2], 1);
 
288
   }
 
289
}
 
290
 
 
291
void brw_gs_quad_strip( struct brw_gs_compile *c, struct brw_gs_prog_key *key )
 
292
{
 
293
   struct intel_context *intel = &c->func.brw->intel;
 
294
 
 
295
   brw_gs_alloc_regs(c, 4, false);
 
296
   brw_gs_initialize_header(c);
 
297
   
 
298
   if (intel->needs_ff_sync)
 
299
      brw_gs_ff_sync(c, 1);
 
300
   brw_gs_overwrite_header_dw2(
 
301
      c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
 
302
          | URB_WRITE_PRIM_START));
 
303
   if (key->pv_first) {
 
304
      brw_gs_emit_vue(c, c->reg.vertex[0], 0);
 
305
      brw_gs_overwrite_header_dw2(
 
306
         c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
 
307
      brw_gs_emit_vue(c, c->reg.vertex[1], 0);
 
308
      brw_gs_emit_vue(c, c->reg.vertex[2], 0);
 
309
      brw_gs_overwrite_header_dw2(
 
310
         c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
 
311
             | URB_WRITE_PRIM_END));
 
312
      brw_gs_emit_vue(c, c->reg.vertex[3], 1);
 
313
   }
 
314
   else {
 
315
      brw_gs_emit_vue(c, c->reg.vertex[2], 0);
 
316
      brw_gs_overwrite_header_dw2(
 
317
         c, _3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT);
 
318
      brw_gs_emit_vue(c, c->reg.vertex[3], 0);
 
319
      brw_gs_emit_vue(c, c->reg.vertex[0], 0);
 
320
      brw_gs_overwrite_header_dw2(
 
321
         c, ((_3DPRIM_POLYGON << URB_WRITE_PRIM_TYPE_SHIFT)
 
322
             | URB_WRITE_PRIM_END));
 
323
      brw_gs_emit_vue(c, c->reg.vertex[1], 1);
 
324
   }
 
325
}
 
326
 
 
327
void brw_gs_lines( struct brw_gs_compile *c )
 
328
{
 
329
   struct intel_context *intel = &c->func.brw->intel;
 
330
 
 
331
   brw_gs_alloc_regs(c, 2, false);
 
332
   brw_gs_initialize_header(c);
 
333
 
 
334
   if (intel->needs_ff_sync)
 
335
      brw_gs_ff_sync(c, 1);
 
336
   brw_gs_overwrite_header_dw2(
 
337
      c, ((_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
 
338
          | URB_WRITE_PRIM_START));
 
339
   brw_gs_emit_vue(c, c->reg.vertex[0], 0);
 
340
   brw_gs_overwrite_header_dw2(
 
341
      c, ((_3DPRIM_LINESTRIP << URB_WRITE_PRIM_TYPE_SHIFT)
 
342
          | URB_WRITE_PRIM_END));
 
343
   brw_gs_emit_vue(c, c->reg.vertex[1], 1);
 
344
}
 
345
 
 
346
/**
 
347
 * Generate the geometry shader program used on Gen6 to perform stream output
 
348
 * (transform feedback).
 
349
 */
 
350
void
 
351
gen6_sol_program(struct brw_gs_compile *c, struct brw_gs_prog_key *key,
 
352
                 unsigned num_verts, bool check_edge_flags)
 
353
{
 
354
   struct brw_compile *p = &c->func;
 
355
   c->prog_data.svbi_postincrement_value = num_verts;
 
356
 
 
357
   brw_gs_alloc_regs(c, num_verts, true);
 
358
   brw_gs_initialize_header(c);
 
359
 
 
360
   if (key->num_transform_feedback_bindings > 0) {
 
361
      unsigned vertex, binding;
 
362
      struct brw_reg destination_indices_uw =
 
363
         vec8(retype(c->reg.destination_indices, BRW_REGISTER_TYPE_UW));
 
364
 
 
365
      /* Note: since we use the binding table to keep track of buffer offsets
 
366
       * and stride, the GS doesn't need to keep track of a separate pointer
 
367
       * into each buffer; it uses a single pointer which increments by 1 for
 
368
       * each vertex.  So we use SVBI0 for this pointer, regardless of whether
 
369
       * transform feedback is in interleaved or separate attribs mode.
 
370
       *
 
371
       * Make sure that the buffers have enough room for all the vertices.
 
372
       */
 
373
      brw_ADD(p, get_element_ud(c->reg.temp, 0),
 
374
                 get_element_ud(c->reg.SVBI, 0), brw_imm_ud(num_verts));
 
375
      brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_LE,
 
376
                 get_element_ud(c->reg.temp, 0),
 
377
                 get_element_ud(c->reg.SVBI, 4));
 
378
      brw_IF(p, BRW_EXECUTE_1);
 
379
 
 
380
      /* Compute the destination indices to write to.  Usually we use SVBI[0]
 
381
       * + (0, 1, 2).  However, for odd-numbered triangles in tristrips, the
 
382
       * vertices come down the pipeline in reversed winding order, so we need
 
383
       * to flip the order when writing to the transform feedback buffer.  To
 
384
       * ensure that flatshading accuracy is preserved, we need to write them
 
385
       * in order SVBI[0] + (0, 2, 1) if we're using the first provoking
 
386
       * vertex convention, and in order SVBI[0] + (1, 0, 2) if we're using
 
387
       * the last provoking vertex convention.
 
388
       *
 
389
       * Note: since brw_imm_v can only be used in instructions in
 
390
       * packed-word execution mode, and SVBI is a double-word, we need to
 
391
       * first move the appropriate immediate constant ((0, 1, 2), (0, 2, 1),
 
392
       * or (1, 0, 2)) to the destination_indices register, and then add SVBI
 
393
       * using a separate instruction.  Also, since the immediate constant is
 
394
       * expressed as packed words, and we need to load double-words into
 
395
       * destination_indices, we need to intersperse zeros to fill the upper
 
396
       * halves of each double-word.
 
397
       */
 
398
      brw_MOV(p, destination_indices_uw,
 
399
              brw_imm_v(0x00020100)); /* (0, 1, 2) */
 
400
      if (num_verts == 3) {
 
401
         /* Get primitive type into temp register. */
 
402
         brw_AND(p, get_element_ud(c->reg.temp, 0),
 
403
                 get_element_ud(c->reg.R0, 2), brw_imm_ud(0x1f));
 
404
 
 
405
         /* Test if primitive type is TRISTRIP_REVERSE.  We need to do this as
 
406
          * an 8-wide comparison so that the conditional MOV that follows
 
407
          * moves all 8 words correctly.
 
408
          */
 
409
         brw_CMP(p, vec8(brw_null_reg()), BRW_CONDITIONAL_EQ,
 
410
                 get_element_ud(c->reg.temp, 0),
 
411
                 brw_imm_ud(_3DPRIM_TRISTRIP_REVERSE));
 
412
 
 
413
         /* If so, then overwrite destination_indices_uw with the appropriate
 
414
          * reordering.
 
415
          */
 
416
         brw_MOV(p, destination_indices_uw,
 
417
                 brw_imm_v(key->pv_first ? 0x00010200    /* (0, 2, 1) */
 
418
                                         : 0x00020001)); /* (1, 0, 2) */
 
419
         brw_set_predicate_control(p, BRW_PREDICATE_NONE);
 
420
      }
 
421
      brw_ADD(p, c->reg.destination_indices,
 
422
              c->reg.destination_indices, get_element_ud(c->reg.SVBI, 0));
 
423
 
 
424
      /* For each vertex, generate code to output each varying using the
 
425
       * appropriate binding table entry.
 
426
       */
 
427
      for (vertex = 0; vertex < num_verts; ++vertex) {
 
428
         /* Set up the correct destination index for this vertex */
 
429
         brw_MOV(p, get_element_ud(c->reg.header, 5),
 
430
                 get_element_ud(c->reg.destination_indices, vertex));
 
431
 
 
432
         for (binding = 0; binding < key->num_transform_feedback_bindings;
 
433
              ++binding) {
 
434
            unsigned char vert_result =
 
435
               key->transform_feedback_bindings[binding];
 
436
            unsigned char slot = c->vue_map.vert_result_to_slot[vert_result];
 
437
            /* From the Sandybridge PRM, Volume 2, Part 1, Section 4.5.1:
 
438
             *
 
439
             *   "Prior to End of Thread with a URB_WRITE, the kernel must
 
440
             *   ensure that all writes are complete by sending the final
 
441
             *   write as a committed write."
 
442
             */
 
443
            bool final_write =
 
444
               binding == key->num_transform_feedback_bindings - 1 &&
 
445
               vertex == num_verts - 1;
 
446
            struct brw_reg vertex_slot = c->reg.vertex[vertex];
 
447
            vertex_slot.nr += slot / 2;
 
448
            vertex_slot.subnr = (slot % 2) * 16;
 
449
            /* gl_PointSize is stored in VERT_RESULT_PSIZ.w. */
 
450
            vertex_slot.dw1.bits.swizzle = vert_result == VERT_RESULT_PSIZ
 
451
               ? BRW_SWIZZLE_WWWW : key->transform_feedback_swizzles[binding];
 
452
            brw_set_access_mode(p, BRW_ALIGN_16);
 
453
            brw_MOV(p, stride(c->reg.header, 4, 4, 1),
 
454
                    retype(vertex_slot, BRW_REGISTER_TYPE_UD));
 
455
            brw_set_access_mode(p, BRW_ALIGN_1);
 
456
            brw_svb_write(p,
 
457
                          final_write ? c->reg.temp : brw_null_reg(), /* dest */
 
458
                          1, /* msg_reg_nr */
 
459
                          c->reg.header, /* src0 */
 
460
                          SURF_INDEX_SOL_BINDING(binding), /* binding_table_index */
 
461
                          final_write); /* send_commit_msg */
 
462
         }
 
463
      }
 
464
      brw_ENDIF(p);
 
465
 
 
466
      /* Now, reinitialize the header register from R0 to restore the parts of
 
467
       * the register that we overwrote while streaming out transform feedback
 
468
       * data.
 
469
       */
 
470
      brw_gs_initialize_header(c);
 
471
 
 
472
      /* Finally, wait for the write commit to occur so that we can proceed to
 
473
       * other things safely.
 
474
       *
 
475
       * From the Sandybridge PRM, Volume 4, Part 1, Section 3.3:
 
476
       *
 
477
       *   The write commit does not modify the destination register, but
 
478
       *   merely clears the dependency associated with the destination
 
479
       *   register. Thus, a simple “mov” instruction using the register as a
 
480
       *   source is sufficient to wait for the write commit to occur.
 
481
       */
 
482
      brw_MOV(p, c->reg.temp, c->reg.temp);
 
483
   }
 
484
 
 
485
   brw_gs_ff_sync(c, 1);
 
486
 
 
487
   /* If RASTERIZER_DISCARD is enabled, we have nothing further to do, so
 
488
    * release the URB that was just allocated, and terminate the thread.
 
489
    */
 
490
   if (key->rasterizer_discard) {
 
491
      brw_gs_terminate(c);
 
492
      return;
 
493
   }
 
494
 
 
495
   brw_gs_overwrite_header_dw2_from_r0(c);
 
496
   switch (num_verts) {
 
497
   case 1:
 
498
      brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_START | URB_WRITE_PRIM_END);
 
499
      brw_gs_emit_vue(c, c->reg.vertex[0], true);
 
500
      break;
 
501
   case 2:
 
502
      brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_START);
 
503
      brw_gs_emit_vue(c, c->reg.vertex[0], false);
 
504
      brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_END - URB_WRITE_PRIM_START);
 
505
      brw_gs_emit_vue(c, c->reg.vertex[1], true);
 
506
      break;
 
507
   case 3:
 
508
      if (check_edge_flags) {
 
509
         /* Only emit vertices 0 and 1 if this is the first triangle of the
 
510
          * polygon.  Otherwise they are redundant.
 
511
          */
 
512
         brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
 
513
         brw_AND(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
 
514
                 get_element_ud(c->reg.R0, 2),
 
515
                 brw_imm_ud(BRW_GS_EDGE_INDICATOR_0));
 
516
         brw_IF(p, BRW_EXECUTE_1);
 
517
      }
 
518
      brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_START);
 
519
      brw_gs_emit_vue(c, c->reg.vertex[0], false);
 
520
      brw_gs_offset_header_dw2(c, -URB_WRITE_PRIM_START);
 
521
      brw_gs_emit_vue(c, c->reg.vertex[1], false);
 
522
      if (check_edge_flags) {
 
523
         brw_ENDIF(p);
 
524
         /* Only emit vertex 2 in PRIM_END mode if this is the last triangle
 
525
          * of the polygon.  Otherwise leave the primitive incomplete because
 
526
          * there are more polygon vertices coming.
 
527
          */
 
528
         brw_set_conditionalmod(p, BRW_CONDITIONAL_NZ);
 
529
         brw_AND(p, retype(brw_null_reg(), BRW_REGISTER_TYPE_UD),
 
530
                 get_element_ud(c->reg.R0, 2),
 
531
                 brw_imm_ud(BRW_GS_EDGE_INDICATOR_1));
 
532
         brw_set_predicate_control(p, BRW_PREDICATE_NORMAL);
 
533
      }
 
534
      brw_gs_offset_header_dw2(c, URB_WRITE_PRIM_END);
 
535
      brw_set_predicate_control(p, BRW_PREDICATE_NONE);
 
536
      brw_gs_emit_vue(c, c->reg.vertex[2], true);
 
537
      break;
 
538
   }
 
539
}