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