• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mesa 3-D graphics library
3  *
4  * Copyright (C) 2012-2015 LunarG, Inc.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included
14  * in all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  *
24  * Authors:
25  *    Chia-I Wu <olv@lunarg.com>
26  */
27 
28 #include "ilo_debug.h"
29 #include "ilo_state_urb.h"
30 
31 struct urb_configuration {
32    uint8_t vs_pcb_alloc_kb;
33    uint8_t hs_pcb_alloc_kb;
34    uint8_t ds_pcb_alloc_kb;
35    uint8_t gs_pcb_alloc_kb;
36    uint8_t ps_pcb_alloc_kb;
37 
38    uint8_t urb_offset_8kb;
39 
40    uint8_t vs_urb_alloc_8kb;
41    uint8_t hs_urb_alloc_8kb;
42    uint8_t ds_urb_alloc_8kb;
43    uint8_t gs_urb_alloc_8kb;
44 
45    uint8_t vs_entry_rows;
46    uint8_t hs_entry_rows;
47    uint8_t ds_entry_rows;
48    uint8_t gs_entry_rows;
49 
50    int vs_entry_count;
51    int hs_entry_count;
52    int ds_entry_count;
53    int gs_entry_count;
54 };
55 
56 static void
urb_alloc_gen7_pcb(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)57 urb_alloc_gen7_pcb(const struct ilo_dev *dev,
58                    const struct ilo_state_urb_info *info,
59                    struct urb_configuration *conf)
60 {
61    /*
62     * From the Haswell PRM, volume 2b, page 940:
63     *
64     *     "[0,16] (0KB - 16KB) Increments of 1KB DevHSW:GT1, DevHSW:GT2
65     *      [0,32] (0KB - 32KB) Increments of 2KB DevHSW:GT3"
66     */
67    const uint8_t increment_kb =
68       (ilo_dev_gen(dev) >= ILO_GEN(8) ||
69        (ilo_dev_gen(dev) == ILO_GEN(7.5) && dev->gt == 3)) ? 2 : 1;
70 
71    ILO_DEV_ASSERT(dev, 7, 8);
72 
73    /*
74     * Keep the strategy simple as we do not know the workloads and how
75     * expensive it is to change the configuration frequently.
76     */
77    if (info->hs_const_data || info->ds_const_data) {
78       conf->vs_pcb_alloc_kb = increment_kb * 4;
79       conf->hs_pcb_alloc_kb = increment_kb * 3;
80       conf->ds_pcb_alloc_kb = increment_kb * 3;
81       conf->gs_pcb_alloc_kb = increment_kb * 3;
82       conf->ps_pcb_alloc_kb = increment_kb * 3;
83    } else if (info->gs_const_data) {
84       conf->vs_pcb_alloc_kb = increment_kb * 6;
85       conf->gs_pcb_alloc_kb = increment_kb * 5;
86       conf->ps_pcb_alloc_kb = increment_kb * 5;
87    } else {
88       conf->vs_pcb_alloc_kb = increment_kb * 8;
89       conf->ps_pcb_alloc_kb = increment_kb * 8;
90    }
91 
92    conf->urb_offset_8kb = increment_kb * 16 / 8;
93 }
94 
95 static void
urb_alloc_gen6_urb(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)96 urb_alloc_gen6_urb(const struct ilo_dev *dev,
97                    const struct ilo_state_urb_info *info,
98                    struct urb_configuration *conf)
99 {
100    /*
101     * From the Ivy Bridge PRM, volume 2 part 1, page 34:
102     *
103     *     "(VS URB Starting Address) Offset from the start of the URB memory
104     *      where VS starts its allocation, specified in multiples of 8 KB."
105     *
106     * Same for other stages.
107     */
108    const int space_avail_8kb = dev->urb_size / 8192 - conf->urb_offset_8kb;
109 
110    /*
111     * From the Sandy Bridge PRM, volume 2 part 1, page 173:
112     *
113     *     "Programming Note: If the GS stage is enabled, software must always
114     *      allocate at least one GS URB Entry. This is true even if the GS
115     *      thread never needs to output vertices to the urb, e.g., when only
116     *      performing stream output. This is an artifact of the need to pass
117     *      the GS thread an initial destination URB handle."
118     */
119    const bool force_gs_alloc =
120       (ilo_dev_gen(dev) == ILO_GEN(6) && info->gs_enable);
121 
122    ILO_DEV_ASSERT(dev, 6, 8);
123 
124    if (info->hs_entry_size || info->ds_entry_size) {
125       conf->vs_urb_alloc_8kb = space_avail_8kb / 4;
126       conf->hs_urb_alloc_8kb = space_avail_8kb / 4;
127       conf->ds_urb_alloc_8kb = space_avail_8kb / 4;
128       conf->gs_urb_alloc_8kb = space_avail_8kb / 4;
129 
130       if (space_avail_8kb % 4) {
131          assert(space_avail_8kb % 2 == 0);
132          conf->vs_urb_alloc_8kb++;
133          conf->gs_urb_alloc_8kb++;
134       }
135    } else if (info->gs_entry_size || force_gs_alloc) {
136       assert(space_avail_8kb % 2 == 0);
137       conf->vs_urb_alloc_8kb = space_avail_8kb / 2;
138       conf->gs_urb_alloc_8kb = space_avail_8kb / 2;
139    } else {
140       conf->vs_urb_alloc_8kb = space_avail_8kb;
141    }
142 }
143 
144 static bool
urb_init_gen6_vs_entry(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)145 urb_init_gen6_vs_entry(const struct ilo_dev *dev,
146                        const struct ilo_state_urb_info *info,
147                        struct urb_configuration *conf)
148 {
149    /*
150     * From the Sandy Bridge PRM, volume 2 part 1, page 28:
151     *
152     *     "(VS URB Entry Allocation Size)
153     *      Range [0,4] = [1,5] 1024-bit URB rows"
154     *
155     *     "(VS Number of URB Entries)
156     *      Range [24,256] in multiples of 4
157     *            [24, 128] in multiples of 4[DevSNBGT1]"
158     */
159    const int max_entry_count = (dev->gt == 2) ? 256 : 252;
160    const int row_size = 1024 / 8;
161    int row_count, entry_count;
162    int entry_size;
163 
164    ILO_DEV_ASSERT(dev, 6, 6);
165 
166    /* VE and VS share the same VUE for each vertex */
167    entry_size = info->vs_entry_size;
168    if (entry_size < info->ve_entry_size)
169       entry_size = info->ve_entry_size;
170 
171    row_count = (entry_size + row_size - 1) / row_size;
172    if (row_count > 5)
173       return false;
174    else if (!row_count)
175       row_count++;
176 
177    entry_count = conf->vs_urb_alloc_8kb * 8192 / (row_size * row_count);
178    if (entry_count > max_entry_count)
179       entry_count = max_entry_count;
180    entry_count &= ~3;
181    assert(entry_count >= 24);
182 
183    conf->vs_entry_rows = row_count;
184    conf->vs_entry_count = entry_count;
185 
186    return true;
187 }
188 
189 static bool
urb_init_gen6_gs_entry(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)190 urb_init_gen6_gs_entry(const struct ilo_dev *dev,
191                        const struct ilo_state_urb_info *info,
192                        struct urb_configuration *conf)
193 {
194    /*
195     * From the Sandy Bridge PRM, volume 2 part 1, page 29:
196     *
197     *     "(GS Number of URB Entries)
198     *      Range [0,256] in multiples of 4
199     *            [0, 254] in multiples of 4[DevSNBGT1]"
200     *
201     *     "(GS URB Entry Allocation Size)
202     *      Range [0,4] = [1,5] 1024-bit URB rows"
203     */
204    const int max_entry_count = (dev->gt == 2) ? 256 : 252;
205    const int row_size = 1024 / 8;
206    int row_count, entry_count;
207 
208    ILO_DEV_ASSERT(dev, 6, 6);
209 
210    row_count = (info->gs_entry_size + row_size - 1) / row_size;
211    if (row_count > 5)
212       return false;
213    else if (!row_count)
214       row_count++;
215 
216    entry_count = conf->gs_urb_alloc_8kb * 8192 / (row_size * row_count);
217    if (entry_count > max_entry_count)
218       entry_count = max_entry_count;
219    entry_count &= ~3;
220 
221    conf->gs_entry_rows = row_count;
222    conf->gs_entry_count = entry_count;
223 
224    return true;
225 }
226 
227 static bool
urb_init_gen7_vs_entry(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)228 urb_init_gen7_vs_entry(const struct ilo_dev *dev,
229                        const struct ilo_state_urb_info *info,
230                        struct urb_configuration *conf)
231 {
232    /*
233     * From the Ivy Bridge PRM, volume 2 part 1, page 34-35:
234     *
235     *     "VS URB Entry Allocation Size equal to 4(5 512-bit URB rows) may
236     *      cause performance to decrease due to banking in the URB. Element
237     *      sizes of 16 to 20 should be programmed with six 512-bit URB rows."
238     *
239     *     "(VS URB Entry Allocation Size)
240     *      Format: U9-1 count of 512-bit units"
241     *
242     *     "(VS Number of URB Entries)
243     *      [32,704]
244     *      [32,512]
245     *
246     *      Programming Restriction: VS Number of URB Entries must be divisible
247     *      by 8 if the VS URB Entry Allocation Size is less than 9 512-bit URB
248     *      entries."2:0" = reserved "000b""
249     *
250     * From the Haswell PRM, volume 2b, page 847:
251     *
252     *     "(VS Number of URB Entries)
253     *      [64,1664] DevHSW:GT3
254     *      [64,1664] DevHSW:GT2
255     *      [32,640]  DevHSW:GT1"
256     */
257    const int row_size = 512 / 8;
258    int row_count, entry_count;
259    int entry_size;
260    int max_entry_count, min_entry_count;
261 
262    ILO_DEV_ASSERT(dev, 7, 8);
263 
264    /*
265     * From the Ivy Bridge PRM, volume 2 part 1, page 35:
266     *
267     *     "Programming Restriction: As the VS URB entry serves as both the
268     *      per-vertex input and output of the VS shader, the VS URB Allocation
269     *      Size must be sized to the maximum of the vertex input and output
270     *      structures."
271     *
272     * From the Ivy Bridge PRM, volume 2 part 1, page 42:
273     *
274     *     "If the VS function is enabled, the VF-written VUEs are not required
275     *      to have Vertex Headers, as the VS-incoming vertices are guaranteed
276     *      to be consumed by the VS (i.e., the VS thread is responsible for
277     *      overwriting the input vertex data)."
278     *
279     * VE and VS share the same VUE for each vertex.
280     */
281    entry_size = info->vs_entry_size;
282    if (entry_size < info->ve_entry_size)
283       entry_size = info->ve_entry_size;
284 
285    row_count = (entry_size + row_size - 1) / row_size;
286    if (row_count == 5 || !row_count)
287       row_count++;
288 
289    entry_count = conf->vs_urb_alloc_8kb * 8192 / (row_size * row_count);
290    if (row_count < 9)
291       entry_count &= ~7;
292 
293    switch (ilo_dev_gen(dev)) {
294    case ILO_GEN(8):
295    case ILO_GEN(7.5):
296       max_entry_count = (dev->gt >= 2) ? 1664 : 640;
297       min_entry_count = (dev->gt >= 2) ? 64 : 32;
298       break;
299    case ILO_GEN(7):
300       max_entry_count = (dev->gt == 2) ? 704 : 512;
301       min_entry_count = 32;
302       break;
303    default:
304       assert(!"unexpected gen");
305       return false;
306       break;
307    }
308 
309    if (entry_count > max_entry_count)
310       entry_count = max_entry_count;
311    else if (entry_count < min_entry_count)
312       return false;
313 
314    conf->vs_entry_rows = row_count;
315    conf->vs_entry_count = entry_count;
316 
317    return true;
318 }
319 
320 static bool
urb_init_gen7_hs_entry(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)321 urb_init_gen7_hs_entry(const struct ilo_dev *dev,
322                        const struct ilo_state_urb_info *info,
323                        struct urb_configuration *conf)
324 {
325    /*
326     * From the Ivy Bridge PRM, volume 2 part 1, page 37:
327     *
328     *     "HS Number of URB Entries must be divisible by 8 if the HS URB Entry
329     *      Allocation Size is less than 9 512-bit URB
330     *      entries."2:0" = reserved "000"
331     *
332     *      [0,64]
333     *      [0,32]"
334     *
335     * From the Haswell PRM, volume 2b, page 849:
336     *
337     *     "(HS Number of URB Entries)
338     *      [0,128] DevHSW:GT2
339     *      [0,64]  DevHSW:GT1"
340     */
341    const int row_size = 512 / 8;
342    int row_count, entry_count;
343    int max_entry_count;
344 
345    ILO_DEV_ASSERT(dev, 7, 8);
346 
347    row_count = (info->hs_entry_size + row_size - 1) / row_size;
348    if (!row_count)
349       row_count++;
350 
351    entry_count = conf->hs_urb_alloc_8kb * 8192 / (row_size * row_count);
352    if (row_count < 9)
353       entry_count &= ~7;
354 
355    switch (ilo_dev_gen(dev)) {
356    case ILO_GEN(8):
357    case ILO_GEN(7.5):
358       max_entry_count = (dev->gt >= 2) ? 128 : 64;
359       break;
360    case ILO_GEN(7):
361       max_entry_count = (dev->gt == 2) ? 64 : 32;
362       break;
363    default:
364       assert(!"unexpected gen");
365       return false;
366       break;
367    }
368 
369    if (entry_count > max_entry_count)
370       entry_count = max_entry_count;
371    else if (info->hs_entry_size && !entry_count)
372       return false;
373 
374    conf->hs_entry_rows = row_count;
375    conf->hs_entry_count = entry_count;
376 
377    return true;
378 }
379 
380 static bool
urb_init_gen7_ds_entry(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)381 urb_init_gen7_ds_entry(const struct ilo_dev *dev,
382                        const struct ilo_state_urb_info *info,
383                        struct urb_configuration *conf)
384 {
385    /*
386     * From the Ivy Bridge PRM, volume 2 part 1, page 38:
387     *
388     *     "(DS URB Entry Allocation Size)
389     *      [0,9]"
390     *
391     *     "(DS Number of URB Entries) If Domain Shader Thread Dispatch is
392     *      Enabled then the minimum number handles that must be allocated is
393     *      138 URB entries.
394     *      "2:0" = reserved "000"
395     *
396     *      [0,448]
397     *      [0,288]
398     *
399     *      DS Number of URB Entries must be divisible by 8 if the DS URB Entry
400     *      Allocation Size is less than 9 512-bit URB entries.If Domain Shader
401     *      Thread Dispatch is Enabled then the minimum number of handles that
402     *      must be allocated is 10 URB entries."
403     *
404     * From the Haswell PRM, volume 2b, page 851:
405     *
406     *     "(DS Number of URB Entries)
407     *      [0,960] DevHSW:GT2
408     *      [0,384] DevHSW:GT1"
409     */
410    const int row_size = 512 / 8;
411    int row_count, entry_count;
412    int max_entry_count;
413 
414    ILO_DEV_ASSERT(dev, 7, 8);
415 
416    row_count = (info->ds_entry_size + row_size - 1) / row_size;
417    if (row_count > 10)
418       return false;
419    else if (!row_count)
420       row_count++;
421 
422    entry_count = conf->ds_urb_alloc_8kb * 8192 / (row_size * row_count);
423    if (row_count < 9)
424       entry_count &= ~7;
425 
426    switch (ilo_dev_gen(dev)) {
427    case ILO_GEN(8):
428    case ILO_GEN(7.5):
429       max_entry_count = (dev->gt >= 2) ? 960 : 384;
430       break;
431    case ILO_GEN(7):
432       max_entry_count = (dev->gt == 2) ? 448 : 288;
433       break;
434    default:
435       assert(!"unexpected gen");
436       return false;
437       break;
438    }
439 
440    if (entry_count > max_entry_count)
441       entry_count = max_entry_count;
442    else if (info->ds_entry_size && entry_count < 10)
443       return false;
444 
445    conf->ds_entry_rows = row_count;
446    conf->ds_entry_count = entry_count;
447 
448    return true;
449 }
450 
451 static bool
urb_init_gen7_gs_entry(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)452 urb_init_gen7_gs_entry(const struct ilo_dev *dev,
453                        const struct ilo_state_urb_info *info,
454                        struct urb_configuration *conf)
455 {
456    /*
457     * From the Ivy Bridge PRM, volume 2 part 1, page 40:
458     *
459     *     "(GS Number of URB Entries) GS Number of URB Entries must be
460     *      divisible by 8 if the GS URB Entry Allocation Size is less than 9
461     *      512-bit URB entries.
462     *      "2:0" = reserved "000"
463     *
464     *      [0,320]
465     *      [0,192]"
466     *
467     * From the Ivy Bridge PRM, volume 2 part 1, page 171:
468     *
469     *     "(DUAL_INSTANCE and DUAL_OBJECT) The GS must be allocated at least
470     *      two URB handles or behavior is UNDEFINED."
471     *
472     * From the Haswell PRM, volume 2b, page 853:
473     *
474     *     "(GS Number of URB Entries)
475     *      [0,640] DevHSW:GT2
476     *      [0,256] DevHSW:GT1
477     *
478     *      Only if GS is disabled can this field be programmed to 0.  If GS is
479     *      enabled this field shall be programmed to a value greater than 0.
480     *      For GS Dispatch Mode "Single", this field shall be programmed to a
481     *      value greater than or equal to 1. For other GS Dispatch Modes,
482     *      refer to the definition of Dispatch Mode (3DSTATE_GS) for minimum
483     *      values of this field."
484     */
485    const int row_size = 512 / 8;
486    int row_count, entry_count;
487    int max_entry_count;
488 
489    ILO_DEV_ASSERT(dev, 7, 8);
490 
491    row_count = (info->gs_entry_size + row_size - 1) / row_size;
492    if (!row_count)
493       row_count++;
494 
495    entry_count = conf->gs_urb_alloc_8kb * 8192 / (row_size * row_count);
496    if (row_count < 9)
497       entry_count &= ~7;
498 
499    switch (ilo_dev_gen(dev)) {
500    case ILO_GEN(8):
501    case ILO_GEN(7.5):
502       max_entry_count = (dev->gt >= 2) ? 640 : 256;
503       break;
504    case ILO_GEN(7):
505       max_entry_count = (dev->gt == 2) ? 320 : 192;
506       break;
507    default:
508       assert(!"unexpected gen");
509       return false;
510       break;
511    }
512 
513    if (entry_count > max_entry_count)
514       entry_count = max_entry_count;
515    else if (info->gs_entry_size && entry_count < 2)
516       return false;
517 
518    conf->gs_entry_rows = row_count;
519    conf->gs_entry_count = entry_count;
520 
521    return true;
522 }
523 
524 static bool
urb_get_gen6_configuration(const struct ilo_dev * dev,const struct ilo_state_urb_info * info,struct urb_configuration * conf)525 urb_get_gen6_configuration(const struct ilo_dev *dev,
526                            const struct ilo_state_urb_info *info,
527                            struct urb_configuration *conf)
528 {
529    ILO_DEV_ASSERT(dev, 6, 8);
530 
531    memset(conf, 0, sizeof(*conf));
532 
533    if (ilo_dev_gen(dev) >= ILO_GEN(7))
534       urb_alloc_gen7_pcb(dev, info, conf);
535 
536    urb_alloc_gen6_urb(dev, info, conf);
537 
538    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
539       if (!urb_init_gen7_vs_entry(dev, info, conf) ||
540           !urb_init_gen7_hs_entry(dev, info, conf) ||
541           !urb_init_gen7_ds_entry(dev, info, conf) ||
542           !urb_init_gen7_gs_entry(dev, info, conf))
543          return false;
544    } else {
545       if (!urb_init_gen6_vs_entry(dev, info, conf) ||
546           !urb_init_gen6_gs_entry(dev, info, conf))
547          return false;
548    }
549 
550    return true;
551 }
552 
553 static bool
urb_set_gen7_3dstate_push_constant_alloc(struct ilo_state_urb * urb,const struct ilo_dev * dev,const struct ilo_state_urb_info * info,const struct urb_configuration * conf)554 urb_set_gen7_3dstate_push_constant_alloc(struct ilo_state_urb *urb,
555                                          const struct ilo_dev *dev,
556                                          const struct ilo_state_urb_info *info,
557                                          const struct urb_configuration *conf)
558 {
559    uint32_t dw1[5];
560    uint8_t sizes_kb[5], offset_kb;
561    int i;
562 
563    ILO_DEV_ASSERT(dev, 7, 8);
564 
565    sizes_kb[0] = conf->vs_pcb_alloc_kb;
566    sizes_kb[1] = conf->hs_pcb_alloc_kb;
567    sizes_kb[2] = conf->ds_pcb_alloc_kb;
568    sizes_kb[3] = conf->gs_pcb_alloc_kb;
569    sizes_kb[4] = conf->ps_pcb_alloc_kb;
570    offset_kb = 0;
571 
572    for (i = 0; i < 5; i++) {
573       /* careful for the valid range of offsets */
574       if (sizes_kb[i]) {
575          dw1[i] = offset_kb << GEN7_PCB_ALLOC_DW1_OFFSET__SHIFT |
576                   sizes_kb[i] << GEN7_PCB_ALLOC_DW1_SIZE__SHIFT;
577          offset_kb += sizes_kb[i];
578       } else {
579          dw1[i] = 0;
580       }
581    }
582 
583    STATIC_ASSERT(ARRAY_SIZE(urb->pcb) >= 5);
584    memcpy(urb->pcb, dw1, sizeof(dw1));
585 
586    return true;
587 }
588 
589 static bool
urb_set_gen6_3DSTATE_URB(struct ilo_state_urb * urb,const struct ilo_dev * dev,const struct ilo_state_urb_info * info,const struct urb_configuration * conf)590 urb_set_gen6_3DSTATE_URB(struct ilo_state_urb *urb,
591                          const struct ilo_dev *dev,
592                          const struct ilo_state_urb_info *info,
593                          const struct urb_configuration *conf)
594 {
595    uint32_t dw1, dw2;
596 
597    ILO_DEV_ASSERT(dev, 6, 6);
598 
599    assert(conf->vs_entry_rows && conf->gs_entry_rows);
600 
601    dw1 = (conf->vs_entry_rows - 1) << GEN6_URB_DW1_VS_ENTRY_SIZE__SHIFT |
602          conf->vs_entry_count << GEN6_URB_DW1_VS_ENTRY_COUNT__SHIFT;
603    dw2 = conf->gs_entry_count << GEN6_URB_DW2_GS_ENTRY_COUNT__SHIFT |
604          (conf->gs_entry_rows - 1) << GEN6_URB_DW2_GS_ENTRY_SIZE__SHIFT;
605 
606    STATIC_ASSERT(ARRAY_SIZE(urb->urb) >= 2);
607    urb->urb[0] = dw1;
608    urb->urb[1] = dw2;
609 
610    return true;
611 }
612 
613 static bool
urb_set_gen7_3dstate_urb(struct ilo_state_urb * urb,const struct ilo_dev * dev,const struct ilo_state_urb_info * info,const struct urb_configuration * conf)614 urb_set_gen7_3dstate_urb(struct ilo_state_urb *urb,
615                          const struct ilo_dev *dev,
616                          const struct ilo_state_urb_info *info,
617                          const struct urb_configuration *conf)
618 {
619    uint32_t dw1[4];
620    struct {
621       uint8_t alloc_8kb;
622       uint8_t entry_rows;
623       int entry_count;
624    } stages[4];
625    uint8_t offset_8kb;
626    int i;
627 
628    ILO_DEV_ASSERT(dev, 7, 8);
629 
630    stages[0].alloc_8kb = conf->vs_urb_alloc_8kb;
631    stages[1].alloc_8kb = conf->hs_urb_alloc_8kb;
632    stages[2].alloc_8kb = conf->ds_urb_alloc_8kb;
633    stages[3].alloc_8kb = conf->gs_urb_alloc_8kb;
634 
635    stages[0].entry_rows = conf->vs_entry_rows;
636    stages[1].entry_rows = conf->hs_entry_rows;
637    stages[2].entry_rows = conf->ds_entry_rows;
638    stages[3].entry_rows = conf->gs_entry_rows;
639 
640    stages[0].entry_count = conf->vs_entry_count;
641    stages[1].entry_count = conf->hs_entry_count;
642    stages[2].entry_count = conf->ds_entry_count;
643    stages[3].entry_count = conf->gs_entry_count;
644 
645    offset_8kb = conf->urb_offset_8kb;
646 
647    for (i = 0; i < 4; i++) {
648       /* careful for the valid range of offsets */
649       if (stages[i].alloc_8kb) {
650          assert(stages[i].entry_rows);
651          dw1[i] =
652             offset_8kb << GEN7_URB_DW1_OFFSET__SHIFT |
653             (stages[i].entry_rows - 1) << GEN7_URB_DW1_ENTRY_SIZE__SHIFT |
654             stages[i].entry_count << GEN7_URB_DW1_ENTRY_COUNT__SHIFT;
655          offset_8kb += stages[i].alloc_8kb;
656       } else {
657          dw1[i] = 0;
658       }
659    }
660 
661    STATIC_ASSERT(ARRAY_SIZE(urb->urb) >= 4);
662    memcpy(urb->urb, dw1, sizeof(dw1));
663 
664    return true;
665 }
666 
667 bool
ilo_state_urb_init(struct ilo_state_urb * urb,const struct ilo_dev * dev,const struct ilo_state_urb_info * info)668 ilo_state_urb_init(struct ilo_state_urb *urb,
669                    const struct ilo_dev *dev,
670                    const struct ilo_state_urb_info *info)
671 {
672    assert(ilo_is_zeroed(urb, sizeof(*urb)));
673    return ilo_state_urb_set_info(urb, dev, info);
674 }
675 
676 bool
ilo_state_urb_init_for_rectlist(struct ilo_state_urb * urb,const struct ilo_dev * dev,uint8_t vf_attr_count)677 ilo_state_urb_init_for_rectlist(struct ilo_state_urb *urb,
678                                 const struct ilo_dev *dev,
679                                 uint8_t vf_attr_count)
680 {
681    struct ilo_state_urb_info info;
682 
683    memset(&info, 0, sizeof(info));
684    info.ve_entry_size = sizeof(uint32_t) * 4 * vf_attr_count;
685 
686    return ilo_state_urb_init(urb, dev, &info);
687 }
688 
689 bool
ilo_state_urb_set_info(struct ilo_state_urb * urb,const struct ilo_dev * dev,const struct ilo_state_urb_info * info)690 ilo_state_urb_set_info(struct ilo_state_urb *urb,
691                        const struct ilo_dev *dev,
692                        const struct ilo_state_urb_info *info)
693 {
694    struct urb_configuration conf;
695    bool ret = true;
696 
697    ret &= urb_get_gen6_configuration(dev, info, &conf);
698    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
699       ret &= urb_set_gen7_3dstate_push_constant_alloc(urb, dev, info, &conf);
700       ret &= urb_set_gen7_3dstate_urb(urb, dev, info, &conf);
701    } else {
702       ret &= urb_set_gen6_3DSTATE_URB(urb, dev, info, &conf);
703    }
704 
705    assert(ret);
706 
707    return ret;
708 }
709 
710 void
ilo_state_urb_full_delta(const struct ilo_state_urb * urb,const struct ilo_dev * dev,struct ilo_state_urb_delta * delta)711 ilo_state_urb_full_delta(const struct ilo_state_urb *urb,
712                          const struct ilo_dev *dev,
713                          struct ilo_state_urb_delta *delta)
714 {
715    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
716       delta->dirty = ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_VS |
717                      ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_HS |
718                      ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_DS |
719                      ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_GS |
720                      ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_PS |
721                      ILO_STATE_URB_3DSTATE_URB_VS |
722                      ILO_STATE_URB_3DSTATE_URB_HS |
723                      ILO_STATE_URB_3DSTATE_URB_DS |
724                      ILO_STATE_URB_3DSTATE_URB_GS;
725    } else {
726       delta->dirty = ILO_STATE_URB_3DSTATE_URB_VS |
727                      ILO_STATE_URB_3DSTATE_URB_GS;
728    }
729 }
730 
731 void
ilo_state_urb_get_delta(const struct ilo_state_urb * urb,const struct ilo_dev * dev,const struct ilo_state_urb * old,struct ilo_state_urb_delta * delta)732 ilo_state_urb_get_delta(const struct ilo_state_urb *urb,
733                         const struct ilo_dev *dev,
734                         const struct ilo_state_urb *old,
735                         struct ilo_state_urb_delta *delta)
736 {
737    delta->dirty = 0;
738 
739    if (ilo_dev_gen(dev) >= ILO_GEN(7)) {
740       if (memcmp(urb->pcb, old->pcb, sizeof(urb->pcb))) {
741          delta->dirty |= ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_VS |
742                          ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_HS |
743                          ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_DS |
744                          ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_GS |
745                          ILO_STATE_URB_3DSTATE_PUSH_CONSTANT_ALLOC_PS;
746       }
747 
748       /*
749        * From the Ivy Bridge PRM, volume 2 part 1, page 34:
750        *
751        *     "3DSTATE_URB_HS, 3DSTATE_URB_DS, and 3DSTATE_URB_GS must also be
752        *      programmed in order for the programming of this state
753        *      (3DSTATE_URB_VS) to be valid."
754        *
755        * The same is true for the other three states.
756        */
757       if (memcmp(urb->urb, old->urb, sizeof(urb->urb))) {
758          delta->dirty |= ILO_STATE_URB_3DSTATE_URB_VS |
759                          ILO_STATE_URB_3DSTATE_URB_HS |
760                          ILO_STATE_URB_3DSTATE_URB_DS |
761                          ILO_STATE_URB_3DSTATE_URB_GS;
762       }
763    } else {
764       if (memcmp(urb->urb, old->urb, sizeof(uint32_t) * 2)) {
765          delta->dirty |= ILO_STATE_URB_3DSTATE_URB_VS |
766                          ILO_STATE_URB_3DSTATE_URB_GS;
767       }
768    }
769 }
770