genX_blorp_exec.c revision 16a9fcbbb688537ac2e8f952e683d63eb7c688e8
1/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include <assert.h>
25
26#include "intel_batchbuffer.h"
27#include "intel_mipmap_tree.h"
28
29#include "brw_context.h"
30#include "brw_state.h"
31
32#include "blorp_priv.h"
33
34#include "genxml/gen_macros.h"
35
36static void *
37blorp_emit_dwords(struct brw_context *brw, unsigned n)
38{
39   intel_batchbuffer_begin(brw, n, RENDER_RING);
40   uint32_t *map = brw->batch.map_next;
41   brw->batch.map_next += n;
42   intel_batchbuffer_advance(brw);
43   return map;
44}
45
46struct blorp_address {
47   drm_intel_bo *buffer;
48   uint32_t read_domains;
49   uint32_t write_domain;
50   uint32_t offset;
51};
52
53static uint64_t
54blorp_emit_reloc(struct brw_context *brw, void *location,
55                 struct blorp_address address, uint32_t delta)
56{
57   uint32_t offset = (char *)location - (char *)brw->batch.map;
58   if (brw->gen >= 8) {
59      return intel_batchbuffer_reloc64(brw, address.buffer, offset,
60                                       address.read_domains,
61                                       address.write_domain,
62                                       address.offset + delta);
63   } else {
64      return intel_batchbuffer_reloc(brw, address.buffer, offset,
65                                     address.read_domains,
66                                     address.write_domain,
67                                     address.offset + delta);
68   }
69}
70
71#define __gen_address_type struct blorp_address
72#define __gen_user_data struct brw_context
73
74static uint64_t
75__gen_combine_address(struct brw_context *brw, void *location,
76                      struct blorp_address address, uint32_t delta)
77{
78   if (address.buffer == NULL) {
79      return address.offset + delta;
80   } else {
81      return blorp_emit_reloc(brw, location, address, delta);
82   }
83}
84
85#include "genxml/genX_pack.h"
86
87#define _blorp_cmd_length(cmd) cmd ## _length
88#define _blorp_cmd_length_bias(cmd) cmd ## _length_bias
89#define _blorp_cmd_header(cmd) cmd ## _header
90#define _blorp_cmd_pack(cmd) cmd ## _pack
91
92#define blorp_emit(brw, cmd, name)                                \
93   for (struct cmd name = { _blorp_cmd_header(cmd) },             \
94        *_dst = blorp_emit_dwords(brw, _blorp_cmd_length(cmd));   \
95        __builtin_expect(_dst != NULL, 1);                        \
96        _blorp_cmd_pack(cmd)(brw, (void *)_dst, &name),           \
97        _dst = NULL)
98
99#define blorp_emitn(batch, cmd, n) ({                    \
100      uint32_t *_dw = blorp_emit_dwords(batch, n);       \
101      struct cmd template = {                            \
102         _blorp_cmd_header(cmd),                         \
103         .DWordLength = n - _blorp_cmd_length_bias(cmd), \
104      };                                                 \
105      _blorp_cmd_pack(cmd)(batch, _dw, &template);       \
106      _dw + 1; /* Array starts at dw[1] */               \
107   })
108
109/* Once vertex fetcher has written full VUE entries with complete
110 * header the space requirement is as follows per vertex (in bytes):
111 *
112 *     Header    Position    Program constants
113 *   +--------+------------+-------------------+
114 *   |   16   |     16     |      n x 16       |
115 *   +--------+------------+-------------------+
116 *
117 * where 'n' stands for number of varying inputs expressed as vec4s.
118 *
119 * The URB size is in turn expressed in 64 bytes (512 bits).
120 */
121static inline unsigned
122gen7_blorp_get_vs_entry_size(const struct brw_blorp_params *params)
123{
124    const unsigned num_varyings =
125       params->wm_prog_data ? params->wm_prog_data->num_varying_inputs : 0;
126    const unsigned total_needed = 16 + 16 + num_varyings * 16;
127
128   return DIV_ROUND_UP(total_needed, 64);
129}
130
131/* 3DSTATE_URB
132/* 3DSTATE_URB_VS
133 * 3DSTATE_URB_HS
134 * 3DSTATE_URB_DS
135 * 3DSTATE_URB_GS
136 *
137 * Assign the entire URB to the VS. Even though the VS disabled, URB space
138 * is still needed because the clipper loads the VUE's from the URB. From
139 * the Sandybridge PRM, Volume 2, Part 1, Section 3DSTATE,
140 * Dword 1.15:0 "VS Number of URB Entries":
141 *     This field is always used (even if VS Function Enable is DISABLED).
142 *
143 * The warning below appears in the PRM (Section 3DSTATE_URB), but we can
144 * safely ignore it because this batch contains only one draw call.
145 *     Because of URB corruption caused by allocating a previous GS unit
146 *     URB entry to the VS unit, software is required to send a “GS NULL
147 *     Fence” (Send URB fence with VS URB size == 1 and GS URB size == 0)
148 *     plus a dummy DRAW call before any case where VS will be taking over
149 *     GS URB space.
150 *
151 * If the 3DSTATE_URB_VS is emitted, than the others must be also.
152 * From the Ivybridge PRM, Volume 2 Part 1, section 1.7.1 3DSTATE_URB_VS:
153 *
154 *     3DSTATE_URB_HS, 3DSTATE_URB_DS, and 3DSTATE_URB_GS must also be
155 *     programmed in order for the programming of this state to be
156 *     valid.
157 */
158static void
159emit_urb_config(struct brw_context *brw,
160                const struct brw_blorp_params *params)
161{
162#if GEN_GEN >= 7
163   const unsigned vs_entry_size = gen7_blorp_get_vs_entry_size(params);
164
165   if (!(brw->ctx.NewDriverState & (BRW_NEW_CONTEXT | BRW_NEW_URB_SIZE)) &&
166       brw->urb.vsize >= vs_entry_size)
167      return;
168
169   brw->ctx.NewDriverState |= BRW_NEW_URB_SIZE;
170
171   gen7_upload_urb(brw, vs_entry_size, false, false);
172#else
173   blorp_emit(brw, GENX(3DSTATE_URB), urb) {
174      urb.VSNumberofURBEntries = brw->urb.max_vs_entries;
175   }
176#endif
177}
178
179static void
180blorp_emit_vertex_data(struct brw_context *brw,
181                       const struct brw_blorp_params *params,
182                       struct blorp_address *addr,
183                       uint32_t *size)
184{
185   const float vertices[] = {
186      /* v0 */ (float)params->x0, (float)params->y1,
187      /* v1 */ (float)params->x1, (float)params->y1,
188      /* v2 */ (float)params->x0, (float)params->y0,
189   };
190
191   uint32_t offset;
192   void *data = brw_state_batch(brw, AUB_TRACE_VERTEX_BUFFER,
193                                sizeof(vertices), 32, &offset);
194   memcpy(data, vertices, sizeof(vertices));
195
196   *addr = (struct blorp_address) {
197      .buffer = brw->batch.bo,
198      .read_domains = I915_GEM_DOMAIN_VERTEX,
199      .write_domain = 0,
200      .offset = offset,
201   };
202   *size = sizeof(vertices);
203}
204
205static void
206blorp_emit_input_varying_data(struct brw_context *brw,
207                              const struct brw_blorp_params *params,
208                              struct blorp_address *addr,
209                              uint32_t *size)
210{
211   const unsigned vec4_size_in_bytes = 4 * sizeof(float);
212   const unsigned max_num_varyings =
213      DIV_ROUND_UP(sizeof(params->wm_inputs), vec4_size_in_bytes);
214   const unsigned num_varyings = params->wm_prog_data->num_varying_inputs;
215
216   *size = num_varyings * vec4_size_in_bytes;
217
218   const float *const inputs_src = (const float *)&params->wm_inputs;
219   uint32_t offset;
220   float *inputs = brw_state_batch(brw, AUB_TRACE_VERTEX_BUFFER,
221                                   *size, 32, &offset);
222
223   /* Walk over the attribute slots, determine if the attribute is used by
224    * the program and when necessary copy the values from the input storage to
225    * the vertex data buffer.
226    */
227   for (unsigned i = 0; i < max_num_varyings; i++) {
228      const gl_varying_slot attr = VARYING_SLOT_VAR0 + i;
229
230      if (!(params->wm_prog_data->inputs_read & BITFIELD64_BIT(attr)))
231         continue;
232
233      memcpy(inputs, inputs_src + i * 4, vec4_size_in_bytes);
234
235      inputs += 4;
236   }
237
238   *addr = (struct blorp_address) {
239      .buffer = brw->batch.bo,
240      .read_domains = I915_GEM_DOMAIN_VERTEX,
241      .write_domain = 0,
242      .offset = offset,
243   };
244}
245
246static void
247blorp_emit_vertex_buffers(struct brw_context *brw,
248                          const struct brw_blorp_params *params)
249{
250   struct GENX(VERTEX_BUFFER_STATE) vb[2];
251   memset(vb, 0, sizeof(vb));
252
253   unsigned num_buffers = 1;
254
255#if GEN_GEN == 9
256   uint32_t mocs = (2 << 1); /* SKL_MOCS_WB */
257#elif GEN_GEN == 8
258   uint32_t mocs = 0x78; /* BDW_MOCS_WB */
259#elif GEN_GEN == 7
260   uint32_t mocs = 1; /* GEN7_MOCS_L3 */
261#else
262   uint32_t mocs = 0;
263#endif
264
265   uint32_t size;
266   blorp_emit_vertex_data(brw, params, &vb[0].BufferStartingAddress, &size);
267   vb[0].VertexBufferIndex = 0;
268   vb[0].BufferPitch = 2 * sizeof(float);
269   vb[0].VertexBufferMOCS = mocs;
270#if GEN_GEN >= 7
271   vb[0].AddressModifyEnable = true;
272#endif
273#if GEN_GEN >= 8
274   vb[0].BufferSize = size;
275#else
276   vb[0].BufferAccessType = VERTEXDATA;
277   vb[0].EndAddress = vb[0].BufferStartingAddress;
278   vb[0].EndAddress.offset += size - 1;
279#endif
280
281   if (params->wm_prog_data && params->wm_prog_data->num_varying_inputs) {
282      blorp_emit_input_varying_data(brw, params,
283                                    &vb[1].BufferStartingAddress, &size);
284      vb[1].VertexBufferIndex = 1;
285      vb[1].BufferPitch = 0;
286      vb[1].VertexBufferMOCS = mocs;
287#if GEN_GEN >= 7
288      vb[1].AddressModifyEnable = true;
289#endif
290#if GEN_GEN >= 8
291      vb[1].BufferSize = size;
292#else
293      vb[1].BufferAccessType = INSTANCEDATA;
294      vb[1].EndAddress = vb[1].BufferStartingAddress;
295      vb[1].EndAddress.offset += size - 1;
296#endif
297      num_buffers++;
298   }
299
300   const unsigned num_dwords =
301      1 + GENX(VERTEX_BUFFER_STATE_length) * num_buffers;
302   uint32_t *dw = blorp_emitn(brw, GENX(3DSTATE_VERTEX_BUFFERS), num_dwords);
303
304   for (unsigned i = 0; i < num_buffers; i++) {
305      GENX(VERTEX_BUFFER_STATE_pack)(brw, dw, &vb[i]);
306      dw += GENX(VERTEX_BUFFER_STATE_length);
307   }
308}
309
310static void
311blorp_emit_vertex_elements(struct brw_context *brw,
312                           const struct brw_blorp_params *params)
313{
314   const unsigned num_varyings =
315      params->wm_prog_data ? params->wm_prog_data->num_varying_inputs : 0;
316   const unsigned num_elements = 2 + num_varyings;
317
318   struct GENX(VERTEX_ELEMENT_STATE) ve[num_elements];
319   memset(ve, 0, num_elements * sizeof(*ve));
320
321   /* Setup VBO for the rectangle primitive..
322    *
323    * A rectangle primitive (3DPRIM_RECTLIST) consists of only three
324    * vertices. The vertices reside in screen space with DirectX
325    * coordinates (that is, (0, 0) is the upper left corner).
326    *
327    *   v2 ------ implied
328    *    |        |
329    *    |        |
330    *   v0 ----- v1
331    *
332    * Since the VS is disabled, the clipper loads each VUE directly from
333    * the URB. This is controlled by the 3DSTATE_VERTEX_BUFFERS and
334    * 3DSTATE_VERTEX_ELEMENTS packets below. The VUE contents are as follows:
335    *   dw0: Reserved, MBZ.
336    *   dw1: Render Target Array Index. The HiZ op does not use indexed
337    *        vertices, so set the dword to 0.
338    *   dw2: Viewport Index. The HiZ op disables viewport mapping and
339    *        scissoring, so set the dword to 0.
340    *   dw3: Point Width: The HiZ op does not emit the POINTLIST primitive,
341    *        so set the dword to 0.
342    *   dw4: Vertex Position X.
343    *   dw5: Vertex Position Y.
344    *   dw6: Vertex Position Z.
345    *   dw7: Vertex Position W.
346    *
347    *   dw8: Flat vertex input 0
348    *   dw9: Flat vertex input 1
349    *   ...
350    *   dwn: Flat vertex input n - 8
351    *
352    * For details, see the Sandybridge PRM, Volume 2, Part 1, Section 1.5.1
353    * "Vertex URB Entry (VUE) Formats".
354    *
355    * Only vertex position X and Y are going to be variable, Z is fixed to
356    * zero and W to one. Header words dw0-3 are all zero. There is no need to
357    * include the fixed values in the vertex buffer. Vertex fetcher can be
358    * instructed to fill vertex elements with constant values of one and zero
359    * instead of reading them from the buffer.
360    * Flat inputs are program constants that are not interpolated. Moreover
361    * their values will be the same between vertices.
362    *
363    * See the vertex element setup below.
364    */
365   ve[0].VertexBufferIndex = 0;
366   ve[0].Valid = true;
367   ve[0].SourceElementFormat = ISL_FORMAT_R32G32B32A32_FLOAT;
368   ve[0].SourceElementOffset = 0;
369   ve[0].Component0Control = VFCOMP_STORE_0;
370   ve[0].Component1Control = VFCOMP_STORE_0;
371   ve[0].Component2Control = VFCOMP_STORE_0;
372   ve[0].Component3Control = VFCOMP_STORE_0;
373
374   ve[1].VertexBufferIndex = 0;
375   ve[1].Valid = true;
376   ve[1].SourceElementFormat = ISL_FORMAT_R32G32_FLOAT;
377   ve[1].SourceElementOffset = 0;
378   ve[1].Component0Control = VFCOMP_STORE_SRC;
379   ve[1].Component1Control = VFCOMP_STORE_SRC;
380   ve[1].Component2Control = VFCOMP_STORE_0;
381   ve[1].Component3Control = VFCOMP_STORE_1_FP;
382
383   for (unsigned i = 0; i < num_varyings; ++i) {
384      ve[i + 2].VertexBufferIndex = 1;
385      ve[i + 2].Valid = true;
386      ve[i + 2].SourceElementFormat = ISL_FORMAT_R32G32B32A32_FLOAT;
387      ve[i + 2].SourceElementOffset = i * 4 * sizeof(float);
388      ve[i + 2].Component0Control = VFCOMP_STORE_SRC;
389      ve[i + 2].Component1Control = VFCOMP_STORE_SRC;
390      ve[i + 2].Component2Control = VFCOMP_STORE_SRC;
391      ve[i + 2].Component3Control = VFCOMP_STORE_SRC;
392   }
393
394   const unsigned num_dwords =
395      1 + GENX(VERTEX_ELEMENT_STATE_length) * num_elements;
396   uint32_t *dw = blorp_emitn(brw, GENX(3DSTATE_VERTEX_ELEMENTS), num_dwords);
397
398   for (unsigned i = 0; i < num_elements; i++) {
399      GENX(VERTEX_ELEMENT_STATE_pack)(brw, dw, &ve[i]);
400      dw += GENX(VERTEX_ELEMENT_STATE_length);
401   }
402
403#if GEN_GEN >= 8
404   blorp_emit(brw, GENX(3DSTATE_VF_SGVS), sgvs);
405
406   for (unsigned i = 0; i < num_elements; i++) {
407      blorp_emit(brw, GENX(3DSTATE_VF_INSTANCING), vf) {
408         vf.VertexElementIndex = i;
409         vf.InstancingEnable = false;
410      }
411   }
412
413   blorp_emit(brw, GENX(3DSTATE_VF_TOPOLOGY), topo) {
414      topo.PrimitiveTopologyType = _3DPRIM_RECTLIST;
415   }
416#endif
417}
418
419static void
420blorp_emit_sf_config(struct brw_context *brw,
421                     const struct brw_blorp_params *params)
422{
423   const struct brw_blorp_prog_data *prog_data = params->wm_prog_data;
424
425   /* 3DSTATE_SF
426    *
427    * Disable ViewportTransformEnable (dw2.1)
428    *
429    * From the SandyBridge PRM, Volume 2, Part 1, Section 1.3, "3D
430    * Primitives Overview":
431    *     RECTLIST: Viewport Mapping must be DISABLED (as is typical with the
432    *     use of screen- space coordinates).
433    *
434    * A solid rectangle must be rendered, so set FrontFaceFillMode (dw2.4:3)
435    * and BackFaceFillMode (dw2.5:6) to SOLID(0).
436    *
437    * From the Sandy Bridge PRM, Volume 2, Part 1, Section
438    * 6.4.1.1 3DSTATE_SF, Field FrontFaceFillMode:
439    *     SOLID: Any triangle or rectangle object found to be front-facing
440    *     is rendered as a solid object. This setting is required when
441    *     (rendering rectangle (RECTLIST) objects.
442    */
443
444#if GEN_GEN >= 8
445
446   blorp_emit(brw, GENX(3DSTATE_SF), sf);
447
448   blorp_emit(brw, GENX(3DSTATE_RASTER), raster) {
449      raster.CullMode = CULLMODE_NONE;
450   }
451
452   blorp_emit(brw, GENX(3DSTATE_SBE), sbe) {
453      sbe.VertexURBEntryReadOffset = BRW_SF_URB_ENTRY_READ_OFFSET;
454      sbe.NumberofSFOutputAttributes = prog_data->num_varying_inputs;
455      sbe.VertexURBEntryReadLength = brw_blorp_get_urb_length(prog_data);
456      sbe.ForceVertexURBEntryReadLength = true;
457      sbe.ForceVertexURBEntryReadOffset = true;
458      sbe.ConstantInterpolationEnable = prog_data->flat_inputs;
459
460#if GEN_GEN >= 9
461      for (unsigned i = 0; i < 32; i++)
462         sbe.AttributeActiveComponentFormat[i] = ACF_XYZW;
463#endif
464   }
465
466#elif GEN_GEN >= 7
467
468   blorp_emit(brw, GENX(3DSTATE_SF), sf) {
469      sf.FrontFaceFillMode = FILL_MODE_SOLID;
470      sf.BackFaceFillMode = FILL_MODE_SOLID;
471
472      sf.MultisampleRasterizationMode = params->dst.surf.samples > 1 ?
473         MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL;
474
475#if GEN_GEN == 7
476      sf.DepthBufferSurfaceFormat = params->depth_format;
477#endif
478   }
479
480   blorp_emit(brw, GENX(3DSTATE_SBE), sbe) {
481      sbe.VertexURBEntryReadOffset = BRW_SF_URB_ENTRY_READ_OFFSET;
482      if (prog_data) {
483         sbe.NumberofSFOutputAttributes = prog_data->num_varying_inputs;
484         sbe.VertexURBEntryReadLength = brw_blorp_get_urb_length(prog_data);
485         sbe.ConstantInterpolationEnable = prog_data->flat_inputs;
486      } else {
487         sbe.NumberofSFOutputAttributes = 0;
488         sbe.VertexURBEntryReadLength = 1;
489      }
490   }
491
492#else /* GEN_GEN <= 6 */
493
494   blorp_emit(brw, GENX(3DSTATE_SF), sf) {
495      sf.FrontFaceFillMode = FILL_MODE_SOLID;
496      sf.BackFaceFillMode = FILL_MODE_SOLID;
497
498      sf.MultisampleRasterizationMode = params->dst.surf.samples > 1 ?
499         MSRASTMODE_ON_PATTERN : MSRASTMODE_OFF_PIXEL;
500
501      sf.VertexURBEntryReadOffset = BRW_SF_URB_ENTRY_READ_OFFSET;
502      if (prog_data) {
503         sf.NumberofSFOutputAttributes = prog_data->num_varying_inputs;
504         sf.VertexURBEntryReadLength = brw_blorp_get_urb_length(prog_data);
505         sf.ConstantInterpolationEnable = prog_data->flat_inputs;
506      } else {
507         sf.NumberofSFOutputAttributes = 0;
508         sf.VertexURBEntryReadLength = 1;
509      }
510   }
511
512#endif /* GEN_GEN */
513}
514
515static void
516blorp_emit_ps_config(struct brw_context *brw,
517                     const struct brw_blorp_params *params)
518{
519   const struct brw_blorp_prog_data *prog_data = params->wm_prog_data;
520
521   /* Even when thread dispatch is disabled, max threads (dw5.25:31) must be
522    * nonzero to prevent the GPU from hanging.  While the documentation doesn't
523    * mention this explicitly, it notes that the valid range for the field is
524    * [1,39] = [2,40] threads, which excludes zero.
525    *
526    * To be safe (and to minimize extraneous code) we go ahead and fully
527    * configure the WM state whether or not there is a WM program.
528    */
529
530#if GEN_GEN >= 8
531
532   blorp_emit(brw, GENX(3DSTATE_WM), wm);
533
534   blorp_emit(brw, GENX(3DSTATE_PS), ps) {
535      if (params->src.bo) {
536         ps.SamplerCount = 1; /* Up to 4 samplers */
537         ps.BindingTableEntryCount = 2;
538      } else {
539         ps.BindingTableEntryCount = 1;
540      }
541
542      ps.DispatchGRFStartRegisterForConstantSetupData0 =
543         prog_data->first_curbe_grf_0;
544      ps.DispatchGRFStartRegisterForConstantSetupData2 =
545         prog_data->first_curbe_grf_2;
546
547      ps._8PixelDispatchEnable = prog_data->dispatch_8;
548      ps._16PixelDispatchEnable = prog_data->dispatch_16;
549
550      ps.KernelStartPointer0 = params->wm_prog_kernel;
551      ps.KernelStartPointer2 =
552         params->wm_prog_kernel + prog_data->ksp_offset_2;
553
554      /* 3DSTATE_PS expects the number of threads per PSD, which is always 64;
555       * it implicitly scales for different GT levels (which have some # of
556       * PSDs).
557       *
558       * In Gen8 the format is U8-2 whereas in Gen9 it is U8-1.
559       */
560      if (GEN_GEN >= 9)
561         ps.MaximumNumberofThreadsPerPSD = 64 - 1;
562      else
563         ps.MaximumNumberofThreadsPerPSD = 64 - 2;
564
565      switch (params->fast_clear_op) {
566#if GEN_GEN >= 9
567      case (1 << 6): /* GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE */
568         ps.RenderTargetResolveType = RESOLVE_PARTIAL;
569         break;
570      case (3 << 6): /* GEN9_PS_RENDER_TARGET_RESOLVE_FULL */
571         ps.RenderTargetResolveType = RESOLVE_FULL;
572         break;
573#else
574      case (1 << 6): /* GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE */
575         ps.RenderTargetResolveEnable = true;
576         break;
577#endif
578      case (1 << 8): /* GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE */
579         ps.RenderTargetFastClearEnable = true;
580         break;
581      }
582   }
583
584   blorp_emit(brw, GENX(3DSTATE_PS_EXTRA), psx) {
585      psx.PixelShaderValid = true;
586
587      if (params->src.bo)
588         psx.PixelShaderKillsPixel = true;
589
590      psx.AttributeEnable = prog_data->num_varying_inputs > 0;
591
592      if (prog_data && prog_data->persample_msaa_dispatch)
593         psx.PixelShaderIsPerSample = true;
594   }
595
596#elif GEN_GEN >= 7
597
598   blorp_emit(brw, GENX(3DSTATE_WM), wm) {
599      switch (params->hiz_op) {
600      case GEN6_HIZ_OP_DEPTH_CLEAR:
601         wm.DepthBufferClear = true;
602         break;
603      case GEN6_HIZ_OP_DEPTH_RESOLVE:
604         wm.DepthBufferResolveEnable = true;
605         break;
606      case GEN6_HIZ_OP_HIZ_RESOLVE:
607         wm.HierarchicalDepthBufferResolveEnable = true;
608         break;
609      case GEN6_HIZ_OP_NONE:
610         break;
611      default:
612         unreachable("not reached");
613      }
614
615      if (prog_data)
616         wm.ThreadDispatchEnable = true;
617
618      if (params->src.bo)
619         wm.PixelShaderKillPixel = true;
620
621      if (params->dst.surf.samples > 1) {
622         wm.MultisampleRasterizationMode = MSRASTMODE_ON_PATTERN;
623         wm.MultisampleDispatchMode =
624            (prog_data && prog_data->persample_msaa_dispatch) ?
625            MSDISPMODE_PERSAMPLE : MSDISPMODE_PERPIXEL;
626      } else {
627         wm.MultisampleRasterizationMode = MSRASTMODE_OFF_PIXEL;
628         wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE;
629      }
630   }
631
632   blorp_emit(brw, GENX(3DSTATE_PS), ps) {
633      ps.MaximumNumberofThreads = brw->max_wm_threads - 1;
634
635#if GEN_IS_HASWELL
636      ps.SampleMask = 1;
637#endif
638
639      if (prog_data) {
640         ps.DispatchGRFStartRegisterforConstantSetupData0 =
641            prog_data->first_curbe_grf_0;
642         ps.DispatchGRFStartRegisterforConstantSetupData2 =
643            prog_data->first_curbe_grf_2;
644
645         ps.KernelStartPointer0 = params->wm_prog_kernel;
646         ps.KernelStartPointer2 =
647            params->wm_prog_kernel + prog_data->ksp_offset_2;
648
649         ps._8PixelDispatchEnable = prog_data->dispatch_8;
650         ps._16PixelDispatchEnable = prog_data->dispatch_16;
651
652         ps.AttributeEnable = prog_data->num_varying_inputs > 0;
653      } else {
654         /* Gen7 hardware gets angry if we don't enable at least one dispatch
655          * mode, so just enable 16-pixel dispatch if we don't have a program.
656          */
657         ps._16PixelDispatchEnable = true;
658      }
659
660      if (params->src.bo)
661         ps.SamplerCount = 1; /* Up to 4 samplers */
662
663      switch (params->fast_clear_op) {
664      case (1 << 6): /* GEN7_PS_RENDER_TARGET_RESOLVE_ENABLE */
665         ps.RenderTargetResolveEnable = true;
666         break;
667      case (1 << 8): /* GEN7_PS_RENDER_TARGET_FAST_CLEAR_ENABLE */
668         ps.RenderTargetFastClearEnable = true;
669         break;
670      }
671   }
672
673#else /* GEN_GEN <= 6 */
674
675   blorp_emit(brw, GENX(3DSTATE_WM), wm) {
676      wm.MaximumNumberofThreads = brw->max_wm_threads - 1;
677
678      switch (params->hiz_op) {
679      case GEN6_HIZ_OP_DEPTH_CLEAR:
680         wm.DepthBufferClear = true;
681         break;
682      case GEN6_HIZ_OP_DEPTH_RESOLVE:
683         wm.DepthBufferResolveEnable = true;
684         break;
685      case GEN6_HIZ_OP_HIZ_RESOLVE:
686         wm.HierarchicalDepthBufferResolveEnable = true;
687         break;
688      case GEN6_HIZ_OP_NONE:
689         break;
690      default:
691         unreachable("not reached");
692      }
693
694      if (prog_data) {
695         wm.ThreadDispatchEnable = true;
696
697         wm.DispatchGRFStartRegisterforConstantSetupData0 =
698            prog_data->first_curbe_grf_0;
699         wm.DispatchGRFStartRegisterforConstantSetupData2 =
700            prog_data->first_curbe_grf_2;
701
702         wm.KernelStartPointer0 = params->wm_prog_kernel;
703         wm.KernelStartPointer2 =
704            params->wm_prog_kernel + prog_data->ksp_offset_2;
705
706         wm._8PixelDispatchEnable = prog_data->dispatch_8;
707         wm._16PixelDispatchEnable = prog_data->dispatch_16;
708
709         wm.NumberofSFOutputAttributes = prog_data->num_varying_inputs;
710      }
711
712      if (params->src.bo) {
713         wm.SamplerCount = 1; /* Up to 4 samplers */
714         wm.PixelShaderKillPixel = true; /* TODO: temporarily smash on */
715      }
716
717      if (params->dst.surf.samples > 1) {
718         wm.MultisampleRasterizationMode = MSRASTMODE_ON_PATTERN;
719         wm.MultisampleDispatchMode =
720            (prog_data && prog_data->persample_msaa_dispatch) ?
721            MSDISPMODE_PERSAMPLE : MSDISPMODE_PERPIXEL;
722      } else {
723         wm.MultisampleRasterizationMode = MSRASTMODE_OFF_PIXEL;
724         wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE;
725      }
726   }
727
728#endif /* GEN_GEN */
729}
730
731
732static void
733blorp_emit_depth_stencil_config(struct brw_context *brw,
734                                const struct brw_blorp_params *params)
735{
736   brw_emit_depth_stall_flushes(brw);
737
738#if GEN_GEN >= 7
739   const uint32_t mocs = 1; /* GEN7_MOCS_L3 */
740#else
741   const uint32_t mocs = 0;
742#endif
743
744   blorp_emit(brw, GENX(3DSTATE_DEPTH_BUFFER), db) {
745      switch (params->depth.surf.dim) {
746      case ISL_SURF_DIM_1D:
747         db.SurfaceType = SURFTYPE_1D;
748         break;
749      case ISL_SURF_DIM_2D:
750         db.SurfaceType = SURFTYPE_2D;
751         break;
752      case ISL_SURF_DIM_3D:
753         db.SurfaceType = SURFTYPE_3D;
754         break;
755      }
756
757      db.SurfaceFormat = params->depth_format;
758
759#if GEN_GEN >= 7
760      db.DepthWriteEnable = true;
761#endif
762
763#if GEN_GEN <= 6
764      db.TiledSurface = true;
765      db.TileWalk = TILEWALK_YMAJOR;
766      db.MIPMapLayoutMode = MIPLAYOUT_BELOW;
767      db.SeparateStencilBufferEnable = true;
768#endif
769
770      db.HierarchicalDepthBufferEnable = true;
771
772      db.Width = params->depth.surf.logical_level0_px.width - 1;
773      db.Height = params->depth.surf.logical_level0_px.height - 1;
774      db.RenderTargetViewExtent = db.Depth =
775         MAX2(params->depth.surf.logical_level0_px.depth,
776              params->depth.surf.logical_level0_px.array_len) - 1;
777
778      db.LOD = params->depth.view.base_level;
779      db.MinimumArrayElement = params->depth.view.base_array_layer;
780
781      db.SurfacePitch = params->depth.surf.row_pitch - 1;
782      db.SurfaceBaseAddress = (struct blorp_address) {
783         .buffer = params->depth.bo,
784         .read_domains = I915_GEM_DOMAIN_RENDER,
785         .write_domain = I915_GEM_DOMAIN_RENDER,
786         .offset = params->depth.offset,
787      };
788      db.DepthBufferMOCS = mocs;
789   }
790
791   blorp_emit(brw, GENX(3DSTATE_HIER_DEPTH_BUFFER), hiz) {
792      hiz.SurfacePitch = params->depth.aux_surf.row_pitch - 1;
793      hiz.SurfaceBaseAddress = (struct blorp_address) {
794         .buffer = params->depth.aux_bo,
795         .read_domains = I915_GEM_DOMAIN_RENDER,
796         .write_domain = I915_GEM_DOMAIN_RENDER,
797         .offset = params->depth.aux_offset,
798      };
799      hiz.HierarchicalDepthBufferMOCS = mocs;
800   }
801
802   blorp_emit(brw, GENX(3DSTATE_STENCIL_BUFFER), sb);
803}
804
805static uint32_t
806blorp_emit_blend_state(struct brw_context *brw,
807                       const struct brw_blorp_params *params)
808{
809   struct GENX(BLEND_STATE) blend;
810   memset(&blend, 0, sizeof(blend));
811
812   for (unsigned i = 0; i < params->num_draw_buffers; ++i) {
813      blend.Entry[i].PreBlendColorClampEnable = true;
814      blend.Entry[i].PostBlendColorClampEnable = true;
815      blend.Entry[i].ColorClampRange = COLORCLAMP_RTFORMAT;
816
817      blend.Entry[i].WriteDisableRed = params->color_write_disable[0];
818      blend.Entry[i].WriteDisableGreen = params->color_write_disable[1];
819      blend.Entry[i].WriteDisableBlue = params->color_write_disable[2];
820      blend.Entry[i].WriteDisableAlpha = params->color_write_disable[3];
821   }
822
823   uint32_t offset;
824   void *state = brw_state_batch(brw, AUB_TRACE_BLEND_STATE,
825                                 GENX(BLEND_STATE_length) * 4, 64, &offset);
826   GENX(BLEND_STATE_pack)(NULL, state, &blend);
827
828#if GEN_GEN >= 7
829   blorp_emit(brw, GENX(3DSTATE_BLEND_STATE_POINTERS), sp) {
830      sp.BlendStatePointer = offset;
831#if GEN_GEN >= 8
832      sp.BlendStatePointerValid = true;
833#endif
834   }
835#endif
836
837#if GEN_GEN >= 8
838   blorp_emit(brw, GENX(3DSTATE_PS_BLEND), ps_blend) {
839      ps_blend.HasWriteableRT = true;
840   }
841#endif
842
843   return offset;
844}
845
846static uint32_t
847blorp_emit_color_calc_state(struct brw_context *brw,
848                            const struct brw_blorp_params *params)
849{
850   uint32_t offset;
851   void *state = brw_state_batch(brw, AUB_TRACE_CC_STATE,
852                                 GENX(COLOR_CALC_STATE_length) * 4, 64, &offset);
853   memset(state, 0, GENX(COLOR_CALC_STATE_length) * 4);
854
855#if GEN_GEN >= 7
856   blorp_emit(brw, GENX(3DSTATE_CC_STATE_POINTERS), sp) {
857      sp.ColorCalcStatePointer = offset;
858#if GEN_GEN >= 8
859      sp.ColorCalcStatePointerValid = true;
860#endif
861   }
862#endif
863
864   return offset;
865}
866
867static uint32_t
868blorp_emit_depth_stencil_state(struct brw_context *brw,
869                               const struct brw_blorp_params *params)
870{
871#if GEN_GEN >= 8
872
873   /* On gen8+, DEPTH_STENCIL state is simply an instruction */
874   blorp_emit(brw, GENX(3DSTATE_WM_DEPTH_STENCIL), ds);
875   return 0;
876
877#else /* GEN_GEN <= 7 */
878
879   /* See the following sections of the Sandy Bridge PRM, Volume 1, Part2:
880    *   - 7.5.3.1 Depth Buffer Clear
881    *   - 7.5.3.2 Depth Buffer Resolve
882    *   - 7.5.3.3 Hierarchical Depth Buffer Resolve
883    */
884   struct GENX(DEPTH_STENCIL_STATE) ds = {
885      .DepthBufferWriteEnable = true,
886   };
887
888   if (params->hiz_op == GEN6_HIZ_OP_DEPTH_RESOLVE) {
889      ds.DepthTestEnable = true;
890      ds.DepthTestFunction = COMPAREFUNCTION_NEVER;
891   }
892
893   uint32_t offset;
894   void *state = brw_state_batch(brw, AUB_TRACE_DEPTH_STENCIL_STATE,
895                                 GENX(DEPTH_STENCIL_STATE_length) * 4, 64,
896                                 &offset);
897   GENX(DEPTH_STENCIL_STATE_pack)(NULL, state, &ds);
898
899#if GEN_GEN >= 7
900   blorp_emit(brw, GENX(3DSTATE_DEPTH_STENCIL_STATE_POINTERS), sp) {
901      sp.PointertoDEPTH_STENCIL_STATE = offset;
902   }
903#endif
904
905   return offset;
906
907#endif /* GEN_GEN */
908}
909
910static void
911blorp_emit_surface_states(struct brw_context *brw,
912                          const struct brw_blorp_params *params)
913{
914   uint32_t bind_offset;
915   uint32_t *bind =
916      brw_state_batch(brw, AUB_TRACE_BINDING_TABLE,
917                      sizeof(uint32_t) * BRW_BLORP_NUM_BINDING_TABLE_ENTRIES,
918                      32, /* alignment */ &bind_offset);
919
920   bind[BRW_BLORP_RENDERBUFFER_BINDING_TABLE_INDEX] =
921      brw_blorp_emit_surface_state(brw, &params->dst,
922                                   I915_GEM_DOMAIN_RENDER,
923                                   I915_GEM_DOMAIN_RENDER, true);
924   if (params->src.bo) {
925      bind[BRW_BLORP_TEXTURE_BINDING_TABLE_INDEX] =
926         brw_blorp_emit_surface_state(brw, &params->src,
927                                      I915_GEM_DOMAIN_SAMPLER, 0, false);
928   }
929
930#if GEN_GEN >= 7
931   blorp_emit(brw, GENX(3DSTATE_BINDING_TABLE_POINTERS_PS), bt) {
932      bt.PointertoPSBindingTable = bind_offset;
933   }
934#else
935   blorp_emit(brw, GENX(3DSTATE_BINDING_TABLE_POINTERS), bt) {
936      bt.PSBindingTableChange = true;
937      bt.PointertoPSBindingTable = bind_offset;
938   }
939#endif
940}
941
942static void
943blorp_emit_sampler_state(struct brw_context *brw,
944                         const struct brw_blorp_params *params)
945{
946   struct GENX(SAMPLER_STATE) sampler = {
947      .MipModeFilter = MIPFILTER_NONE,
948      .MagModeFilter = MAPFILTER_LINEAR,
949      .MinModeFilter = MAPFILTER_LINEAR,
950      .MinLOD = 0,
951      .MaxLOD = 0,
952      .TCXAddressControlMode = TCM_CLAMP,
953      .TCYAddressControlMode = TCM_CLAMP,
954      .TCZAddressControlMode = TCM_CLAMP,
955      .MaximumAnisotropy = RATIO21,
956      .RAddressMinFilterRoundingEnable = true,
957      .RAddressMagFilterRoundingEnable = true,
958      .VAddressMinFilterRoundingEnable = true,
959      .VAddressMagFilterRoundingEnable = true,
960      .UAddressMinFilterRoundingEnable = true,
961      .UAddressMagFilterRoundingEnable = true,
962      .NonnormalizedCoordinateEnable = true,
963   };
964
965   uint32_t offset;
966   void *state = brw_state_batch(brw, AUB_TRACE_SAMPLER_STATE,
967                                 GENX(SAMPLER_STATE_length) * 4, 32, &offset);
968   GENX(SAMPLER_STATE_pack)(NULL, state, &sampler);
969
970#if GEN_GEN >= 7
971   blorp_emit(brw, GENX(3DSTATE_SAMPLER_STATE_POINTERS_PS), ssp) {
972      ssp.PointertoPSSamplerState = offset;
973   }
974#else
975   blorp_emit(brw, GENX(3DSTATE_SAMPLER_STATE_POINTERS), ssp) {
976      ssp.VSSamplerStateChange = true;
977      ssp.GSSamplerStateChange = true;
978      ssp.PSSamplerStateChange = true;
979      ssp.PointertoPSSamplerState = offset;
980   }
981#endif
982}
983
984/* 3DSTATE_VIEWPORT_STATE_POINTERS */
985static void
986blorp_emit_viewport_state(struct brw_context *brw,
987                          const struct brw_blorp_params *params)
988{
989   uint32_t cc_vp_offset;
990
991   void *state = brw_state_batch(brw, AUB_TRACE_CC_VP_STATE,
992                                 GENX(CC_VIEWPORT_length) * 4, 32,
993                                 &cc_vp_offset);
994
995   GENX(CC_VIEWPORT_pack)(brw, state,
996      &(struct GENX(CC_VIEWPORT)) {
997         .MinimumDepth = 0.0,
998         .MaximumDepth = 1.0,
999      });
1000
1001#if GEN_GEN >= 7
1002   blorp_emit(brw, GENX(3DSTATE_VIEWPORT_STATE_POINTERS_CC), vsp) {
1003      vsp.CCViewportPointer = cc_vp_offset;
1004   }
1005#else
1006   blorp_emit(brw, GENX(3DSTATE_VIEWPORT_STATE_POINTERS), vsp) {
1007      vsp.CCViewportStateChange = true;
1008      vsp.PointertoCC_VIEWPORT = cc_vp_offset;
1009   }
1010#endif
1011}
1012
1013
1014/**
1015 * \brief Execute a blit or render pass operation.
1016 *
1017 * To execute the operation, this function manually constructs and emits a
1018 * batch to draw a rectangle primitive. The batchbuffer is flushed before
1019 * constructing and after emitting the batch.
1020 *
1021 * This function alters no GL state.
1022 */
1023void
1024genX(blorp_exec)(struct brw_context *brw,
1025                 const struct brw_blorp_params *params)
1026{
1027   uint32_t blend_state_offset = 0;
1028   uint32_t color_calc_state_offset = 0;
1029   uint32_t depth_stencil_state_offset;
1030
1031#if GEN_GEN == 6
1032   /* Emit workaround flushes when we switch from drawing to blorping. */
1033   brw_emit_post_sync_nonzero_flush(brw);
1034#endif
1035
1036   brw_upload_state_base_address(brw);
1037
1038#if GEN_GEN >= 8
1039   gen7_l3_state.emit(brw);
1040#endif
1041
1042   blorp_emit_vertex_buffers(brw, params);
1043   blorp_emit_vertex_elements(brw, params);
1044
1045   emit_urb_config(brw, params);
1046
1047   if (params->wm_prog_data) {
1048      blend_state_offset = blorp_emit_blend_state(brw, params);
1049      color_calc_state_offset = blorp_emit_color_calc_state(brw, params);
1050   }
1051   depth_stencil_state_offset = blorp_emit_depth_stencil_state(brw, params);
1052
1053#if GEN_GEN <= 6
1054   /* 3DSTATE_CC_STATE_POINTERS
1055    *
1056    * The pointer offsets are relative to
1057    * CMD_STATE_BASE_ADDRESS.DynamicStateBaseAddress.
1058    *
1059    * The HiZ op doesn't use BLEND_STATE or COLOR_CALC_STATE.
1060    *
1061    * The dynamic state emit helpers emit their own STATE_POINTERS packets on
1062    * gen7+.  However, on gen6 and earlier, they're all lumpped together in
1063    * one CC_STATE_POINTERS packet so we have to emit that here.
1064    */
1065   blorp_emit(brw, GENX(3DSTATE_CC_STATE_POINTERS), cc) {
1066      cc.BLEND_STATEChange = true;
1067      cc.COLOR_CALC_STATEChange = true;
1068      cc.DEPTH_STENCIL_STATEChange = true;
1069      cc.PointertoBLEND_STATE = blend_state_offset;
1070      cc.PointertoCOLOR_CALC_STATE = color_calc_state_offset;
1071      cc.PointertoDEPTH_STENCIL_STATE = depth_stencil_state_offset;
1072   }
1073#else
1074   (void)blend_state_offset;
1075   (void)color_calc_state_offset;
1076   (void)depth_stencil_state_offset;
1077#endif
1078
1079   blorp_emit(brw, GENX(3DSTATE_CONSTANT_VS), vs);
1080#if GEN_GEN >= 7
1081   blorp_emit(brw, GENX(3DSTATE_CONSTANT_HS), hs);
1082   blorp_emit(brw, GENX(3DSTATE_CONSTANT_DS), DS);
1083#endif
1084   blorp_emit(brw, GENX(3DSTATE_CONSTANT_GS), gs);
1085   blorp_emit(brw, GENX(3DSTATE_CONSTANT_PS), ps);
1086
1087   if (brw->use_resource_streamer)
1088      gen7_disable_hw_binding_tables(brw);
1089
1090   if (params->wm_prog_data)
1091      blorp_emit_surface_states(brw, params);
1092
1093   if (params->src.bo)
1094      blorp_emit_sampler_state(brw, params);
1095
1096#if GEN_GEN >= 8
1097   gen8_emit_3dstate_multisample(brw, params->dst.surf.samples);
1098#else
1099   gen6_emit_3dstate_multisample(brw, params->dst.surf.samples);
1100#endif
1101
1102   blorp_emit(brw, GENX(3DSTATE_SAMPLE_MASK), mask) {
1103      mask.SampleMask = (1 << params->dst.surf.samples) - 1;
1104   }
1105
1106   /* From the BSpec, 3D Pipeline > Geometry > Vertex Shader > State,
1107    * 3DSTATE_VS, Dword 5.0 "VS Function Enable":
1108    *
1109    *   [DevSNB] A pipeline flush must be programmed prior to a
1110    *   3DSTATE_VS command that causes the VS Function Enable to
1111    *   toggle. Pipeline flush can be executed by sending a PIPE_CONTROL
1112    *   command with CS stall bit set and a post sync operation.
1113    *
1114    * We've already done one at the start of the BLORP operation.
1115    */
1116   blorp_emit(brw, GENX(3DSTATE_VS), vs);
1117#if GEN_GEN >= 7
1118   blorp_emit(brw, GENX(3DSTATE_HS), hs);
1119   blorp_emit(brw, GENX(3DSTATE_TE), te);
1120   blorp_emit(brw, GENX(3DSTATE_DS), DS);
1121   blorp_emit(brw, GENX(3DSTATE_STREAMOUT), so);
1122#endif
1123   blorp_emit(brw, GENX(3DSTATE_GS), gs);
1124
1125   blorp_emit(brw, GENX(3DSTATE_CLIP), clip) {
1126      clip.PerspectiveDivideDisable = true;
1127   }
1128
1129   blorp_emit_sf_config(brw, params);
1130   blorp_emit_ps_config(brw, params);
1131
1132   blorp_emit_viewport_state(brw, params);
1133
1134   if (params->depth.bo) {
1135      blorp_emit_depth_stencil_config(brw, params);
1136   } else {
1137      brw_emit_depth_stall_flushes(brw);
1138
1139      blorp_emit(brw, GENX(3DSTATE_DEPTH_BUFFER), db) {
1140         db.SurfaceType = SURFTYPE_NULL;
1141         db.SurfaceFormat = D32_FLOAT;
1142      }
1143      blorp_emit(brw, GENX(3DSTATE_HIER_DEPTH_BUFFER), hiz);
1144      blorp_emit(brw, GENX(3DSTATE_STENCIL_BUFFER), sb);
1145   }
1146
1147   /* 3DSTATE_CLEAR_PARAMS
1148    *
1149    * From the Sandybridge PRM, Volume 2, Part 1, Section 3DSTATE_CLEAR_PARAMS:
1150    *   [DevSNB] 3DSTATE_CLEAR_PARAMS packet must follow the DEPTH_BUFFER_STATE
1151    *   packet when HiZ is enabled and the DEPTH_BUFFER_STATE changes.
1152    */
1153   blorp_emit(brw, GENX(3DSTATE_CLEAR_PARAMS), clear) {
1154      clear.DepthClearValueValid = true;
1155      clear.DepthClearValue = params->depth.clear_color.u32[0];
1156   }
1157
1158   blorp_emit(brw, GENX(3DSTATE_DRAWING_RECTANGLE), rect) {
1159      rect.ClippedDrawingRectangleXMax = MAX2(params->x1, params->x0) - 1;
1160      rect.ClippedDrawingRectangleYMax = MAX2(params->y1, params->y0) - 1;
1161   }
1162
1163   blorp_emit(brw, GENX(3DPRIMITIVE), prim) {
1164      prim.VertexAccessType = SEQUENTIAL;
1165      prim.PrimitiveTopologyType = _3DPRIM_RECTLIST;
1166      prim.VertexCountPerInstance = 3;
1167      prim.InstanceCount = params->num_layers;
1168   }
1169}
1170