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_vma.h"
30 #include "ilo_state_vf.h"
31
32 static bool
vf_validate_gen6_elements(const struct ilo_dev * dev,const struct ilo_state_vf_info * info)33 vf_validate_gen6_elements(const struct ilo_dev *dev,
34 const struct ilo_state_vf_info *info)
35 {
36 /*
37 * From the Sandy Bridge PRM, volume 2 part 1, page 95:
38 *
39 * "(Source Element Offset (in bytes))
40 * Format: U11
41 * Range [0,2047"
42 *
43 * From the Haswell PRM, volume 2d, page 415:
44 *
45 * "(Source Element Offset)
46 * Format: U12 byte offset
47 * ...
48 * [0,4095]"
49 *
50 * From the Broadwell PRM, volume 2d, page 469:
51 *
52 * "(Source Element Offset)
53 * Format: U12 byte offset
54 * ...
55 * [0,2047]"
56 */
57 const uint16_t max_vertex_offset =
58 (ilo_dev_gen(dev) == ILO_GEN(7.5)) ? 4096 : 2048;
59 uint8_t i;
60
61 ILO_DEV_ASSERT(dev, 6, 8);
62
63 assert(info->element_count <= ILO_STATE_VF_MAX_ELEMENT_COUNT);
64
65 for (i = 0; i < info->element_count; i++) {
66 const struct ilo_state_vf_element_info *elem = &info->elements[i];
67
68 assert(elem->buffer < ILO_STATE_VF_MAX_BUFFER_COUNT);
69 assert(elem->vertex_offset < max_vertex_offset);
70 assert(ilo_state_vf_valid_element_format(dev, elem->format));
71 }
72
73 return true;
74 }
75
76 static uint32_t
get_gen6_component_controls(const struct ilo_dev * dev,enum gen_vf_component comp_x,enum gen_vf_component comp_y,enum gen_vf_component comp_z,enum gen_vf_component comp_w)77 get_gen6_component_controls(const struct ilo_dev *dev,
78 enum gen_vf_component comp_x,
79 enum gen_vf_component comp_y,
80 enum gen_vf_component comp_z,
81 enum gen_vf_component comp_w)
82 {
83 ILO_DEV_ASSERT(dev, 6, 8);
84
85 return comp_x << GEN6_VE_DW1_COMP0__SHIFT |
86 comp_y << GEN6_VE_DW1_COMP1__SHIFT |
87 comp_z << GEN6_VE_DW1_COMP2__SHIFT |
88 comp_w << GEN6_VE_DW1_COMP3__SHIFT;
89 }
90
91 static bool
get_gen6_edge_flag_format(const struct ilo_dev * dev,const struct ilo_state_vf_element_info * elem,enum gen_surface_format * format)92 get_gen6_edge_flag_format(const struct ilo_dev *dev,
93 const struct ilo_state_vf_element_info *elem,
94 enum gen_surface_format *format)
95 {
96 ILO_DEV_ASSERT(dev, 6, 8);
97
98 /*
99 * From the Sandy Bridge PRM, volume 2 part 1, page 94:
100 *
101 * "The Source Element Format must be set to the UINT format."
102 *
103 * From the Haswell PRM, volume 2d, page 413:
104 *
105 * "The SourceElementFormat needs to be a single-component format with
106 * an element which has edge flag enabled."
107 */
108 if (elem->component_count != 1)
109 return false;
110
111 /* pick the format we like */
112 switch (elem->format_size) {
113 case 1:
114 *format = GEN6_FORMAT_R8_UINT;
115 break;
116 case 2:
117 *format = GEN6_FORMAT_R16_UINT;
118 break;
119 case 4:
120 *format = GEN6_FORMAT_R32_UINT;
121 break;
122 default:
123 return false;
124 break;
125 }
126
127 return true;
128 }
129
130 static bool
vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_info * info)131 vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(struct ilo_state_vf *vf,
132 const struct ilo_dev *dev,
133 const struct ilo_state_vf_info *info)
134 {
135 enum gen_surface_format edge_flag_format;
136 uint32_t dw0, dw1;
137 uint8_t i;
138
139 ILO_DEV_ASSERT(dev, 6, 8);
140
141 if (!vf_validate_gen6_elements(dev, info))
142 return false;
143
144 for (i = 0; i < info->element_count; i++) {
145 const struct ilo_state_vf_element_info *elem = &info->elements[i];
146 enum gen_vf_component components[4] = {
147 GEN6_VFCOMP_STORE_0,
148 GEN6_VFCOMP_STORE_0,
149 GEN6_VFCOMP_STORE_0,
150 (elem->is_integer) ? GEN6_VFCOMP_STORE_1_INT :
151 GEN6_VFCOMP_STORE_1_FP,
152 };
153
154 switch (elem->component_count) {
155 case 4: components[3] = GEN6_VFCOMP_STORE_SRC; /* fall through */
156 case 3: components[2] = GEN6_VFCOMP_STORE_SRC; /* fall through */
157 case 2: components[1] = GEN6_VFCOMP_STORE_SRC; /* fall through */
158 case 1: components[0] = GEN6_VFCOMP_STORE_SRC; break;
159 default:
160 assert(!"unexpected component count");
161 break;
162 }
163
164 dw0 = elem->buffer << GEN6_VE_DW0_VB_INDEX__SHIFT |
165 GEN6_VE_DW0_VALID |
166 elem->format << GEN6_VE_DW0_FORMAT__SHIFT |
167 elem->vertex_offset << GEN6_VE_DW0_VB_OFFSET__SHIFT;
168 dw1 = get_gen6_component_controls(dev,
169 components[0], components[1],
170 components[2], components[3]);
171
172 STATIC_ASSERT(ARRAY_SIZE(vf->user_ve[i]) >= 2);
173 vf->user_ve[i][0] = dw0;
174 vf->user_ve[i][1] = dw1;
175 }
176
177 vf->user_ve_count = i;
178
179 vf->edge_flag_supported = (i && get_gen6_edge_flag_format(dev,
180 &info->elements[i - 1], &edge_flag_format));
181 if (vf->edge_flag_supported) {
182 const struct ilo_state_vf_element_info *elem = &info->elements[i - 1];
183
184 /* without edge flag enable */
185 vf->last_user_ve[0][0] = dw0;
186 vf->last_user_ve[0][1] = dw1;
187
188 /*
189 * From the Sandy Bridge PRM, volume 2 part 1, page 94:
190 *
191 * "This bit (Edge Flag Enable) must only be ENABLED on the last
192 * valid VERTEX_ELEMENT structure.
193 *
194 * When set, Component 0 Control must be set to
195 * VFCOMP_STORE_SRC, and Component 1-3 Control must be set to
196 * VFCOMP_NOSTORE."
197 */
198 dw0 = elem->buffer << GEN6_VE_DW0_VB_INDEX__SHIFT |
199 GEN6_VE_DW0_VALID |
200 edge_flag_format << GEN6_VE_DW0_FORMAT__SHIFT |
201 GEN6_VE_DW0_EDGE_FLAG_ENABLE |
202 elem->vertex_offset << GEN6_VE_DW0_VB_OFFSET__SHIFT;
203 dw1 = get_gen6_component_controls(dev, GEN6_VFCOMP_STORE_SRC,
204 GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE, GEN6_VFCOMP_NOSTORE);
205
206 /* with edge flag enable */
207 vf->last_user_ve[1][0] = dw0;
208 vf->last_user_ve[1][1] = dw1;
209 }
210
211 return true;
212 }
213
214 static bool
vf_set_gen6_vertex_buffer_state(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_info * info)215 vf_set_gen6_vertex_buffer_state(struct ilo_state_vf *vf,
216 const struct ilo_dev *dev,
217 const struct ilo_state_vf_info *info)
218 {
219 uint8_t i;
220
221 ILO_DEV_ASSERT(dev, 6, 7.5);
222
223 memset(vf->vb_to_first_elem, -1, sizeof(vf->vb_to_first_elem));
224
225 for (i = 0; i < info->element_count; i++) {
226 const struct ilo_state_vf_element_info *elem = &info->elements[i];
227
228 STATIC_ASSERT(ARRAY_SIZE(vf->user_instancing[i]) >= 2);
229 /* instancing enable only */
230 vf->user_instancing[i][0] = (elem->instancing_enable) ?
231 GEN6_VB_DW0_ACCESS_INSTANCEDATA :
232 GEN6_VB_DW0_ACCESS_VERTEXDATA;
233 vf->user_instancing[i][1] = elem->instancing_step_rate;
234
235 /*
236 * Instancing is per VB, not per VE, before Gen8. Set up a VB-to-VE
237 * mapping as well.
238 */
239 if (vf->vb_to_first_elem[elem->buffer] < 0) {
240 vf->vb_to_first_elem[elem->buffer] = i;
241 } else {
242 const struct ilo_state_vf_element_info *first =
243 &info->elements[vf->vb_to_first_elem[elem->buffer]];
244
245 assert(elem->instancing_enable == first->instancing_enable &&
246 elem->instancing_step_rate == first->instancing_step_rate);
247 }
248 }
249
250 return true;
251 }
252
253 static bool
vf_set_gen8_3DSTATE_VF_INSTANCING(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_info * info)254 vf_set_gen8_3DSTATE_VF_INSTANCING(struct ilo_state_vf *vf,
255 const struct ilo_dev *dev,
256 const struct ilo_state_vf_info *info)
257 {
258 uint8_t i;
259
260 ILO_DEV_ASSERT(dev, 8, 8);
261
262 for (i = 0; i < info->element_count; i++) {
263 const struct ilo_state_vf_element_info *elem = &info->elements[i];
264
265 STATIC_ASSERT(ARRAY_SIZE(vf->user_instancing[i]) >= 2);
266 vf->user_instancing[i][0] = (elem->instancing_enable) ?
267 GEN8_INSTANCING_DW1_ENABLE : 0;
268 vf->user_instancing[i][1] = elem->instancing_step_rate;
269 }
270
271 return true;
272 }
273
274 static uint32_t
get_gen6_component_zeros(const struct ilo_dev * dev)275 get_gen6_component_zeros(const struct ilo_dev *dev)
276 {
277 ILO_DEV_ASSERT(dev, 6, 8);
278
279 return get_gen6_component_controls(dev,
280 GEN6_VFCOMP_STORE_0,
281 GEN6_VFCOMP_STORE_0,
282 GEN6_VFCOMP_STORE_0,
283 GEN6_VFCOMP_STORE_0);
284 }
285
286 static uint32_t
get_gen6_component_ids(const struct ilo_dev * dev,bool vertexid,bool instanceid)287 get_gen6_component_ids(const struct ilo_dev *dev,
288 bool vertexid, bool instanceid)
289 {
290 ILO_DEV_ASSERT(dev, 6, 7.5);
291
292 return get_gen6_component_controls(dev,
293 (vertexid) ? GEN6_VFCOMP_STORE_VID : GEN6_VFCOMP_STORE_0,
294 (instanceid) ? GEN6_VFCOMP_STORE_IID : GEN6_VFCOMP_STORE_0,
295 GEN6_VFCOMP_STORE_0,
296 GEN6_VFCOMP_STORE_0);
297 }
298
299 static bool
vf_params_set_gen6_internal_ve(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_params_info * params,uint8_t user_ve_count)300 vf_params_set_gen6_internal_ve(struct ilo_state_vf *vf,
301 const struct ilo_dev *dev,
302 const struct ilo_state_vf_params_info *params,
303 uint8_t user_ve_count)
304 {
305 const bool prepend_ids =
306 (params->prepend_vertexid || params->prepend_instanceid);
307 uint8_t internal_ve_count = 0, i;
308 uint32_t dw1[2];
309
310
311 ILO_DEV_ASSERT(dev, 6, 8);
312
313 /*
314 * From the Sandy Bridge PRM, volume 2 part 1, page 92:
315 *
316 * "- At least one VERTEX_ELEMENT_STATE structure must be included.
317 *
318 * - Inclusion of partial VERTEX_ELEMENT_STATE structures is
319 * UNDEFINED.
320 *
321 * - SW must ensure that at least one vertex element is defined prior
322 * to issuing a 3DPRIMTIVE command, or operation is UNDEFINED.
323 *
324 * - There are no "holes" allowed in the destination vertex: NOSTORE
325 * components must be overwritten by subsequent components unless
326 * they are the trailing DWords of the vertex. Software must
327 * explicitly chose some value (probably 0) to be written into
328 * DWords that would otherwise be "holes"."
329 *
330 * - ...
331 *
332 * - [DevILK+] Element[0] must be valid."
333 */
334 if (params->prepend_zeros || (!user_ve_count && !prepend_ids))
335 dw1[internal_ve_count++] = get_gen6_component_zeros(dev);
336
337 if (prepend_ids) {
338 if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
339 /* placeholder for 3DSTATE_VF_SGVS */
340 dw1[internal_ve_count++] = get_gen6_component_zeros(dev);
341 } else {
342 dw1[internal_ve_count++] = get_gen6_component_ids(dev,
343 params->prepend_vertexid, params->prepend_instanceid);
344 }
345 }
346
347 for (i = 0; i < internal_ve_count; i++) {
348 STATIC_ASSERT(ARRAY_SIZE(vf->internal_ve[i]) >= 2);
349 vf->internal_ve[i][0] = GEN6_VE_DW0_VALID;
350 vf->internal_ve[i][1] = dw1[i];
351 }
352
353 vf->internal_ve_count = internal_ve_count;
354
355 return true;
356 }
357
358 static bool
vf_params_set_gen8_3DSTATE_VF_SGVS(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_params_info * params)359 vf_params_set_gen8_3DSTATE_VF_SGVS(struct ilo_state_vf *vf,
360 const struct ilo_dev *dev,
361 const struct ilo_state_vf_params_info *params)
362 {
363 const uint8_t attr = (params->prepend_zeros) ? 1 : 0;
364 uint32_t dw1;
365
366 ILO_DEV_ASSERT(dev, 8, 8);
367
368 dw1 = 0;
369
370 if (params->prepend_instanceid) {
371 dw1 |= GEN8_SGVS_DW1_IID_ENABLE |
372 1 << GEN8_SGVS_DW1_IID_COMP__SHIFT |
373 attr << GEN8_SGVS_DW1_IID_OFFSET__SHIFT;
374 }
375
376 if (params->prepend_vertexid) {
377 dw1 |= GEN8_SGVS_DW1_VID_ENABLE |
378 0 << GEN8_SGVS_DW1_VID_COMP__SHIFT |
379 attr << GEN8_SGVS_DW1_VID_OFFSET__SHIFT;
380 }
381
382 STATIC_ASSERT(ARRAY_SIZE(vf->sgvs) >= 1);
383 vf->sgvs[0] = dw1;
384
385 return true;
386 }
387
388 static uint32_t
get_gen6_fixed_cut_index(const struct ilo_dev * dev,enum gen_index_format format)389 get_gen6_fixed_cut_index(const struct ilo_dev *dev,
390 enum gen_index_format format)
391 {
392 const uint32_t fixed = ~0u;
393
394 ILO_DEV_ASSERT(dev, 6, 7);
395
396 switch (format) {
397 case GEN6_INDEX_BYTE: return (uint8_t) fixed;
398 case GEN6_INDEX_WORD: return (uint16_t) fixed;
399 case GEN6_INDEX_DWORD: return (uint32_t) fixed;
400 default:
401 assert(!"unknown index format");
402 return fixed;
403 }
404 }
405
406 static bool
get_gen6_cut_index_supported(const struct ilo_dev * dev,enum gen_3dprim_type topology)407 get_gen6_cut_index_supported(const struct ilo_dev *dev,
408 enum gen_3dprim_type topology)
409 {
410 ILO_DEV_ASSERT(dev, 6, 8);
411
412 /*
413 * See the Sandy Bridge PRM, volume 2 part 1, page 80 and the Haswell PRM,
414 * volume 7, page 456.
415 */
416 switch (topology) {
417 case GEN6_3DPRIM_TRIFAN:
418 case GEN6_3DPRIM_QUADLIST:
419 case GEN6_3DPRIM_QUADSTRIP:
420 case GEN6_3DPRIM_POLYGON:
421 case GEN6_3DPRIM_LINELOOP:
422 return (ilo_dev_gen(dev) >= ILO_GEN(7.5));
423 case GEN6_3DPRIM_RECTLIST:
424 case GEN6_3DPRIM_TRIFAN_NOSTIPPLE:
425 return false;
426 default:
427 return true;
428 }
429 }
430
431 static bool
vf_params_set_gen6_3dstate_index_buffer(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_params_info * params)432 vf_params_set_gen6_3dstate_index_buffer(struct ilo_state_vf *vf,
433 const struct ilo_dev *dev,
434 const struct ilo_state_vf_params_info *params)
435 {
436 uint32_t dw0 = 0;
437
438 ILO_DEV_ASSERT(dev, 6, 7);
439
440 /* cut index only, as in 3DSTATE_VF */
441 if (params->cut_index_enable) {
442 assert(get_gen6_cut_index_supported(dev, params->cv_topology));
443 assert(get_gen6_fixed_cut_index(dev, params->cv_index_format) ==
444 params->cut_index);
445
446 dw0 |= GEN6_IB_DW0_CUT_INDEX_ENABLE;
447 }
448
449 STATIC_ASSERT(ARRAY_SIZE(vf->cut) >= 1);
450 vf->cut[0] = dw0;
451
452 return true;
453 }
454
455 static bool
vf_params_set_gen75_3DSTATE_VF(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_params_info * params)456 vf_params_set_gen75_3DSTATE_VF(struct ilo_state_vf *vf,
457 const struct ilo_dev *dev,
458 const struct ilo_state_vf_params_info *params)
459 {
460 uint32_t dw0 = 0;
461
462 ILO_DEV_ASSERT(dev, 7.5, 8);
463
464 if (params->cut_index_enable) {
465 assert(get_gen6_cut_index_supported(dev, params->cv_topology));
466 dw0 |= GEN75_VF_DW0_CUT_INDEX_ENABLE;
467 }
468
469 STATIC_ASSERT(ARRAY_SIZE(vf->cut) >= 2);
470 vf->cut[0] = dw0;
471 vf->cut[1] = params->cut_index;
472
473 return true;
474 }
475
476 static bool
vertex_buffer_validate_gen6(const struct ilo_dev * dev,const struct ilo_state_vertex_buffer_info * info)477 vertex_buffer_validate_gen6(const struct ilo_dev *dev,
478 const struct ilo_state_vertex_buffer_info *info)
479 {
480 ILO_DEV_ASSERT(dev, 6, 8);
481
482 if (info->vma)
483 assert(info->size && info->offset + info->size <= info->vma->vm_size);
484
485 /*
486 * From the Sandy Bridge PRM, volume 2 part 1, page 86:
487 *
488 * "(Buffer Pitch)
489 * Range [DevCTG+]: [0,2048] Bytes"
490 */
491 assert(info->stride <= 2048);
492
493 /*
494 * From the Sandy Bridge PRM, volume 2 part 1, page 86:
495 *
496 * "64-bit floating point values must be 64-bit aligned in memory, or
497 * UNPREDICTABLE data will be fetched. When accessing an element
498 * containing 64-bit floating point values, the Buffer Starting
499 * Address and Source Element Offset values must add to a 64-bit
500 * aligned address, and BufferPitch must be a multiple of 64-bits."
501 */
502 if (info->cv_has_double) {
503 if (info->vma)
504 assert(info->vma->vm_alignment % 8 == 0);
505
506 assert(info->stride % 8 == 0);
507 assert((info->offset + info->cv_double_vertex_offset_mod_8) % 8 == 0);
508 }
509
510 return true;
511 }
512
513 static uint32_t
vertex_buffer_get_gen6_size(const struct ilo_dev * dev,const struct ilo_state_vertex_buffer_info * info)514 vertex_buffer_get_gen6_size(const struct ilo_dev *dev,
515 const struct ilo_state_vertex_buffer_info *info)
516 {
517 ILO_DEV_ASSERT(dev, 6, 8);
518 return (info->vma) ? info->size : 0;
519 }
520
521 static bool
vertex_buffer_set_gen8_vertex_buffer_state(struct ilo_state_vertex_buffer * vb,const struct ilo_dev * dev,const struct ilo_state_vertex_buffer_info * info)522 vertex_buffer_set_gen8_vertex_buffer_state(struct ilo_state_vertex_buffer *vb,
523 const struct ilo_dev *dev,
524 const struct ilo_state_vertex_buffer_info *info)
525 {
526 const uint32_t size = vertex_buffer_get_gen6_size(dev, info);
527 uint32_t dw0;
528
529 ILO_DEV_ASSERT(dev, 6, 8);
530
531 if (!vertex_buffer_validate_gen6(dev, info))
532 return false;
533
534 dw0 = info->stride << GEN6_VB_DW0_PITCH__SHIFT;
535
536 if (ilo_dev_gen(dev) >= ILO_GEN(7))
537 dw0 |= GEN7_VB_DW0_ADDR_MODIFIED;
538 if (!info->vma)
539 dw0 |= GEN6_VB_DW0_IS_NULL;
540
541 STATIC_ASSERT(ARRAY_SIZE(vb->vb) >= 3);
542 vb->vb[0] = dw0;
543 vb->vb[1] = info->offset;
544
545 if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
546 vb->vb[2] = size;
547 } else {
548 /* address of the last valid byte */
549 vb->vb[2] = (size) ? info->offset + size - 1 : 0;
550 }
551
552 vb->vma = info->vma;
553
554 return true;
555 }
556
557 static uint32_t
get_index_format_size(enum gen_index_format format)558 get_index_format_size(enum gen_index_format format)
559 {
560 switch (format) {
561 case GEN6_INDEX_BYTE: return 1;
562 case GEN6_INDEX_WORD: return 2;
563 case GEN6_INDEX_DWORD: return 4;
564 default:
565 assert(!"unknown index format");
566 return 1;
567 }
568 }
569
570 static bool
index_buffer_validate_gen6(const struct ilo_dev * dev,const struct ilo_state_index_buffer_info * info)571 index_buffer_validate_gen6(const struct ilo_dev *dev,
572 const struct ilo_state_index_buffer_info *info)
573 {
574 const uint32_t format_size = get_index_format_size(info->format);
575
576 ILO_DEV_ASSERT(dev, 6, 8);
577
578 /*
579 * From the Sandy Bridge PRM, volume 2 part 1, page 79:
580 *
581 * "This field (Buffer Starting Address) contains the size-aligned (as
582 * specified by Index Format) Graphics Address of the first element of
583 * interest within the index buffer."
584 */
585 assert(info->offset % format_size == 0);
586
587 if (info->vma) {
588 assert(info->vma->vm_alignment % format_size == 0);
589 assert(info->size && info->offset + info->size <= info->vma->vm_size);
590 }
591
592 return true;
593 }
594
595 static uint32_t
index_buffer_get_gen6_size(const struct ilo_dev * dev,const struct ilo_state_index_buffer_info * info)596 index_buffer_get_gen6_size(const struct ilo_dev *dev,
597 const struct ilo_state_index_buffer_info *info)
598 {
599 uint32_t size;
600
601 ILO_DEV_ASSERT(dev, 6, 8);
602
603 if (!info->vma)
604 return 0;
605
606 size = info->size;
607 if (ilo_dev_gen(dev) < ILO_GEN(8)) {
608 const uint32_t format_size = get_index_format_size(info->format);
609 size -= (size % format_size);
610 }
611
612 return size;
613 }
614
615 static bool
index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(struct ilo_state_index_buffer * ib,const struct ilo_dev * dev,const struct ilo_state_index_buffer_info * info)616 index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(struct ilo_state_index_buffer *ib,
617 const struct ilo_dev *dev,
618 const struct ilo_state_index_buffer_info *info)
619 {
620 const uint32_t size = index_buffer_get_gen6_size(dev, info);
621
622 ILO_DEV_ASSERT(dev, 6, 8);
623
624 if (!index_buffer_validate_gen6(dev, info))
625 return false;
626
627 STATIC_ASSERT(ARRAY_SIZE(ib->ib) >= 3);
628 if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
629 ib->ib[0] = info->format << GEN8_IB_DW1_FORMAT__SHIFT;
630 ib->ib[1] = info->offset;
631 ib->ib[2] = size;
632 } else {
633 ib->ib[0] = info->format << GEN6_IB_DW0_FORMAT__SHIFT;
634 ib->ib[1] = info->offset;
635 /* address of the last valid byte, or 0 */
636 ib->ib[2] = (size) ? info->offset + size - 1 : 0;
637 }
638
639 ib->vma = info->vma;
640
641 return true;
642 }
643
644 bool
ilo_state_vf_valid_element_format(const struct ilo_dev * dev,enum gen_surface_format format)645 ilo_state_vf_valid_element_format(const struct ilo_dev *dev,
646 enum gen_surface_format format)
647 {
648 /*
649 * This table is based on:
650 *
651 * - the Sandy Bridge PRM, volume 4 part 1, page 88-97
652 * - the Ivy Bridge PRM, volume 2 part 1, page 97-99
653 * - the Haswell PRM, volume 7, page 467-470
654 */
655 static const int vf_element_formats[] = {
656 [GEN6_FORMAT_R32G32B32A32_FLOAT] = ILO_GEN( 1),
657 [GEN6_FORMAT_R32G32B32A32_SINT] = ILO_GEN( 1),
658 [GEN6_FORMAT_R32G32B32A32_UINT] = ILO_GEN( 1),
659 [GEN6_FORMAT_R32G32B32A32_UNORM] = ILO_GEN( 1),
660 [GEN6_FORMAT_R32G32B32A32_SNORM] = ILO_GEN( 1),
661 [GEN6_FORMAT_R64G64_FLOAT] = ILO_GEN( 1),
662 [GEN6_FORMAT_R32G32B32A32_SSCALED] = ILO_GEN( 1),
663 [GEN6_FORMAT_R32G32B32A32_USCALED] = ILO_GEN( 1),
664 [GEN6_FORMAT_R32G32B32A32_SFIXED] = ILO_GEN(7.5),
665 [GEN6_FORMAT_R32G32B32_FLOAT] = ILO_GEN( 1),
666 [GEN6_FORMAT_R32G32B32_SINT] = ILO_GEN( 1),
667 [GEN6_FORMAT_R32G32B32_UINT] = ILO_GEN( 1),
668 [GEN6_FORMAT_R32G32B32_UNORM] = ILO_GEN( 1),
669 [GEN6_FORMAT_R32G32B32_SNORM] = ILO_GEN( 1),
670 [GEN6_FORMAT_R32G32B32_SSCALED] = ILO_GEN( 1),
671 [GEN6_FORMAT_R32G32B32_USCALED] = ILO_GEN( 1),
672 [GEN6_FORMAT_R32G32B32_SFIXED] = ILO_GEN(7.5),
673 [GEN6_FORMAT_R16G16B16A16_UNORM] = ILO_GEN( 1),
674 [GEN6_FORMAT_R16G16B16A16_SNORM] = ILO_GEN( 1),
675 [GEN6_FORMAT_R16G16B16A16_SINT] = ILO_GEN( 1),
676 [GEN6_FORMAT_R16G16B16A16_UINT] = ILO_GEN( 1),
677 [GEN6_FORMAT_R16G16B16A16_FLOAT] = ILO_GEN( 1),
678 [GEN6_FORMAT_R32G32_FLOAT] = ILO_GEN( 1),
679 [GEN6_FORMAT_R32G32_SINT] = ILO_GEN( 1),
680 [GEN6_FORMAT_R32G32_UINT] = ILO_GEN( 1),
681 [GEN6_FORMAT_R32G32_UNORM] = ILO_GEN( 1),
682 [GEN6_FORMAT_R32G32_SNORM] = ILO_GEN( 1),
683 [GEN6_FORMAT_R64_FLOAT] = ILO_GEN( 1),
684 [GEN6_FORMAT_R16G16B16A16_SSCALED] = ILO_GEN( 1),
685 [GEN6_FORMAT_R16G16B16A16_USCALED] = ILO_GEN( 1),
686 [GEN6_FORMAT_R32G32_SSCALED] = ILO_GEN( 1),
687 [GEN6_FORMAT_R32G32_USCALED] = ILO_GEN( 1),
688 [GEN6_FORMAT_R32G32_SFIXED] = ILO_GEN(7.5),
689 [GEN6_FORMAT_B8G8R8A8_UNORM] = ILO_GEN( 1),
690 [GEN6_FORMAT_R10G10B10A2_UNORM] = ILO_GEN( 1),
691 [GEN6_FORMAT_R10G10B10A2_UINT] = ILO_GEN( 1),
692 [GEN6_FORMAT_R10G10B10_SNORM_A2_UNORM] = ILO_GEN( 1),
693 [GEN6_FORMAT_R8G8B8A8_UNORM] = ILO_GEN( 1),
694 [GEN6_FORMAT_R8G8B8A8_SNORM] = ILO_GEN( 1),
695 [GEN6_FORMAT_R8G8B8A8_SINT] = ILO_GEN( 1),
696 [GEN6_FORMAT_R8G8B8A8_UINT] = ILO_GEN( 1),
697 [GEN6_FORMAT_R16G16_UNORM] = ILO_GEN( 1),
698 [GEN6_FORMAT_R16G16_SNORM] = ILO_GEN( 1),
699 [GEN6_FORMAT_R16G16_SINT] = ILO_GEN( 1),
700 [GEN6_FORMAT_R16G16_UINT] = ILO_GEN( 1),
701 [GEN6_FORMAT_R16G16_FLOAT] = ILO_GEN( 1),
702 [GEN6_FORMAT_B10G10R10A2_UNORM] = ILO_GEN(7.5),
703 [GEN6_FORMAT_R11G11B10_FLOAT] = ILO_GEN( 1),
704 [GEN6_FORMAT_R32_SINT] = ILO_GEN( 1),
705 [GEN6_FORMAT_R32_UINT] = ILO_GEN( 1),
706 [GEN6_FORMAT_R32_FLOAT] = ILO_GEN( 1),
707 [GEN6_FORMAT_R32_UNORM] = ILO_GEN( 1),
708 [GEN6_FORMAT_R32_SNORM] = ILO_GEN( 1),
709 [GEN6_FORMAT_R10G10B10X2_USCALED] = ILO_GEN( 1),
710 [GEN6_FORMAT_R8G8B8A8_SSCALED] = ILO_GEN( 1),
711 [GEN6_FORMAT_R8G8B8A8_USCALED] = ILO_GEN( 1),
712 [GEN6_FORMAT_R16G16_SSCALED] = ILO_GEN( 1),
713 [GEN6_FORMAT_R16G16_USCALED] = ILO_GEN( 1),
714 [GEN6_FORMAT_R32_SSCALED] = ILO_GEN( 1),
715 [GEN6_FORMAT_R32_USCALED] = ILO_GEN( 1),
716 [GEN6_FORMAT_R8G8_UNORM] = ILO_GEN( 1),
717 [GEN6_FORMAT_R8G8_SNORM] = ILO_GEN( 1),
718 [GEN6_FORMAT_R8G8_SINT] = ILO_GEN( 1),
719 [GEN6_FORMAT_R8G8_UINT] = ILO_GEN( 1),
720 [GEN6_FORMAT_R16_UNORM] = ILO_GEN( 1),
721 [GEN6_FORMAT_R16_SNORM] = ILO_GEN( 1),
722 [GEN6_FORMAT_R16_SINT] = ILO_GEN( 1),
723 [GEN6_FORMAT_R16_UINT] = ILO_GEN( 1),
724 [GEN6_FORMAT_R16_FLOAT] = ILO_GEN( 1),
725 [GEN6_FORMAT_R8G8_SSCALED] = ILO_GEN( 1),
726 [GEN6_FORMAT_R8G8_USCALED] = ILO_GEN( 1),
727 [GEN6_FORMAT_R16_SSCALED] = ILO_GEN( 1),
728 [GEN6_FORMAT_R16_USCALED] = ILO_GEN( 1),
729 [GEN6_FORMAT_R8_UNORM] = ILO_GEN( 1),
730 [GEN6_FORMAT_R8_SNORM] = ILO_GEN( 1),
731 [GEN6_FORMAT_R8_SINT] = ILO_GEN( 1),
732 [GEN6_FORMAT_R8_UINT] = ILO_GEN( 1),
733 [GEN6_FORMAT_R8_SSCALED] = ILO_GEN( 1),
734 [GEN6_FORMAT_R8_USCALED] = ILO_GEN( 1),
735 [GEN6_FORMAT_R8G8B8_UNORM] = ILO_GEN( 1),
736 [GEN6_FORMAT_R8G8B8_SNORM] = ILO_GEN( 1),
737 [GEN6_FORMAT_R8G8B8_SSCALED] = ILO_GEN( 1),
738 [GEN6_FORMAT_R8G8B8_USCALED] = ILO_GEN( 1),
739 [GEN6_FORMAT_R64G64B64A64_FLOAT] = ILO_GEN( 1),
740 [GEN6_FORMAT_R64G64B64_FLOAT] = ILO_GEN( 1),
741 [GEN6_FORMAT_R16G16B16_FLOAT] = ILO_GEN( 6),
742 [GEN6_FORMAT_R16G16B16_UNORM] = ILO_GEN( 1),
743 [GEN6_FORMAT_R16G16B16_SNORM] = ILO_GEN( 1),
744 [GEN6_FORMAT_R16G16B16_SSCALED] = ILO_GEN( 1),
745 [GEN6_FORMAT_R16G16B16_USCALED] = ILO_GEN( 1),
746 [GEN6_FORMAT_R16G16B16_UINT] = ILO_GEN(7.5),
747 [GEN6_FORMAT_R16G16B16_SINT] = ILO_GEN(7.5),
748 [GEN6_FORMAT_R32_SFIXED] = ILO_GEN(7.5),
749 [GEN6_FORMAT_R10G10B10A2_SNORM] = ILO_GEN(7.5),
750 [GEN6_FORMAT_R10G10B10A2_USCALED] = ILO_GEN(7.5),
751 [GEN6_FORMAT_R10G10B10A2_SSCALED] = ILO_GEN(7.5),
752 [GEN6_FORMAT_R10G10B10A2_SINT] = ILO_GEN(7.5),
753 [GEN6_FORMAT_B10G10R10A2_SNORM] = ILO_GEN(7.5),
754 [GEN6_FORMAT_B10G10R10A2_USCALED] = ILO_GEN(7.5),
755 [GEN6_FORMAT_B10G10R10A2_SSCALED] = ILO_GEN(7.5),
756 [GEN6_FORMAT_B10G10R10A2_UINT] = ILO_GEN(7.5),
757 [GEN6_FORMAT_B10G10R10A2_SINT] = ILO_GEN(7.5),
758 [GEN6_FORMAT_R8G8B8_UINT] = ILO_GEN(7.5),
759 [GEN6_FORMAT_R8G8B8_SINT] = ILO_GEN(7.5),
760 };
761
762 ILO_DEV_ASSERT(dev, 6, 8);
763
764 return (format < ARRAY_SIZE(vf_element_formats) &&
765 vf_element_formats[format] &&
766 ilo_dev_gen(dev) >= vf_element_formats[format]);
767 }
768
769 bool
ilo_state_vf_init(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_info * info)770 ilo_state_vf_init(struct ilo_state_vf *vf,
771 const struct ilo_dev *dev,
772 const struct ilo_state_vf_info *info)
773 {
774 bool ret = true;
775
776 assert(ilo_is_zeroed(vf, sizeof(*vf)));
777 assert(ilo_is_zeroed(info->data, info->data_size));
778
779 assert(ilo_state_vf_data_size(dev, info->element_count) <=
780 info->data_size);
781 vf->user_ve = (uint32_t (*)[2]) info->data;
782 vf->user_instancing =
783 (uint32_t (*)[2]) (vf->user_ve + info->element_count);
784
785 ret &= vf_set_gen6_3DSTATE_VERTEX_ELEMENTS(vf, dev, info);
786
787 if (ilo_dev_gen(dev) >= ILO_GEN(8))
788 ret &= vf_set_gen8_3DSTATE_VF_INSTANCING(vf, dev, info);
789 else
790 ret &= vf_set_gen6_vertex_buffer_state(vf, dev, info);
791
792 ret &= ilo_state_vf_set_params(vf, dev, &info->params);
793
794 assert(ret);
795
796 return ret;
797 }
798
799 bool
ilo_state_vf_init_for_rectlist(struct ilo_state_vf * vf,const struct ilo_dev * dev,void * data,size_t data_size,const struct ilo_state_vf_element_info * elements,uint8_t element_count)800 ilo_state_vf_init_for_rectlist(struct ilo_state_vf *vf,
801 const struct ilo_dev *dev,
802 void *data, size_t data_size,
803 const struct ilo_state_vf_element_info *elements,
804 uint8_t element_count)
805 {
806 struct ilo_state_vf_info info;
807
808 memset(&info, 0, sizeof(info));
809
810 info.data = data;
811 info.data_size = data_size;
812
813 info.elements = elements;
814 info.element_count = element_count;
815
816 /*
817 * For VUE header,
818 *
819 * DW0: Reserved: MBZ
820 * DW1: Render Target Array Index
821 * DW2: Viewport Index
822 * DW3: Point Width
823 */
824 info.params.prepend_zeros = true;
825
826 return ilo_state_vf_init(vf, dev, &info);
827 }
828
829 bool
ilo_state_vf_set_params(struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf_params_info * params)830 ilo_state_vf_set_params(struct ilo_state_vf *vf,
831 const struct ilo_dev *dev,
832 const struct ilo_state_vf_params_info *params)
833 {
834 bool ret = true;
835
836 ILO_DEV_ASSERT(dev, 6, 8);
837
838 ret &= vf_params_set_gen6_internal_ve(vf, dev, params, vf->user_ve_count);
839 if (ilo_dev_gen(dev) >= ILO_GEN(8))
840 ret &= vf_params_set_gen8_3DSTATE_VF_SGVS(vf, dev, params);
841
842 /*
843 * From the Sandy Bridge PRM, volume 2 part 1, page 94:
844 *
845 * "Edge flags are supported for the following primitive topology types
846 * only, otherwise EdgeFlagEnable must not be ENABLED.
847 *
848 * - 3DPRIM_TRILIST*
849 * - 3DPRIM_TRISTRIP*
850 * - 3DPRIM_TRIFAN*
851 * - 3DPRIM_POLYGON"
852 *
853 * "[DevSNB]: Edge Flags are not supported for QUADLIST primitives.
854 * Software may elect to convert QUADLIST primitives to some set of
855 * corresponding edge-flag-supported primitive types (e.g., POLYGONs)
856 * prior to submission to the 3D vf."
857 *
858 * From the Ivy Bridge PRM, volume 2 part 1, page 86:
859 *
860 * "Edge flags are supported for all primitive topology types."
861 *
862 * Both PRMs are confusing...
863 */
864 if (params->last_element_edge_flag) {
865 assert(vf->edge_flag_supported);
866 if (ilo_dev_gen(dev) == ILO_GEN(6))
867 assert(params->cv_topology != GEN6_3DPRIM_QUADLIST);
868 }
869
870 if (vf->edge_flag_supported) {
871 assert(vf->user_ve_count);
872 memcpy(vf->user_ve[vf->user_ve_count - 1],
873 vf->last_user_ve[params->last_element_edge_flag],
874 sizeof(vf->user_ve[vf->user_ve_count - 1]));
875 }
876
877 if (ilo_dev_gen(dev) >= ILO_GEN(7.5))
878 ret &= vf_params_set_gen75_3DSTATE_VF(vf, dev, params);
879 else
880 ret &= vf_params_set_gen6_3dstate_index_buffer(vf, dev, params);
881
882 assert(ret);
883
884 return ret;
885 }
886
887 void
ilo_state_vf_full_delta(const struct ilo_state_vf * vf,const struct ilo_dev * dev,struct ilo_state_vf_delta * delta)888 ilo_state_vf_full_delta(const struct ilo_state_vf *vf,
889 const struct ilo_dev *dev,
890 struct ilo_state_vf_delta *delta)
891 {
892 delta->dirty = ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS;
893
894 if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
895 delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS |
896 ILO_STATE_VF_3DSTATE_VF_INSTANCING;
897 } else {
898 delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS;
899 }
900
901 if (ilo_dev_gen(dev) >= ILO_GEN(7.5))
902 delta->dirty |= ILO_STATE_VF_3DSTATE_VF;
903 else
904 delta->dirty |= ILO_STATE_VF_3DSTATE_INDEX_BUFFER;
905 }
906
907 void
ilo_state_vf_get_delta(const struct ilo_state_vf * vf,const struct ilo_dev * dev,const struct ilo_state_vf * old,struct ilo_state_vf_delta * delta)908 ilo_state_vf_get_delta(const struct ilo_state_vf *vf,
909 const struct ilo_dev *dev,
910 const struct ilo_state_vf *old,
911 struct ilo_state_vf_delta *delta)
912 {
913 /* no shallow copying */
914 assert(vf->user_ve != old->user_ve &&
915 vf->user_instancing != old->user_instancing);
916
917 delta->dirty = 0;
918
919 if (vf->internal_ve_count != old->internal_ve_count ||
920 vf->user_ve_count != old->user_ve_count ||
921 memcmp(vf->internal_ve, old->internal_ve,
922 sizeof(vf->internal_ve[0]) * vf->internal_ve_count) ||
923 memcmp(vf->user_ve, old->user_ve,
924 sizeof(vf->user_ve[0]) * vf->user_ve_count))
925 delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_ELEMENTS;
926
927 if (vf->user_ve_count != old->user_ve_count ||
928 memcmp(vf->user_instancing, old->user_instancing,
929 sizeof(vf->user_instancing[0]) * vf->user_ve_count)) {
930 if (ilo_dev_gen(dev) >= ILO_GEN(8))
931 delta->dirty |= ILO_STATE_VF_3DSTATE_VF_INSTANCING;
932 else
933 delta->dirty |= ILO_STATE_VF_3DSTATE_VERTEX_BUFFERS;
934 }
935
936 if (ilo_dev_gen(dev) >= ILO_GEN(8)) {
937 if (vf->sgvs[0] != old->sgvs[0])
938 delta->dirty |= ILO_STATE_VF_3DSTATE_VF_SGVS;
939 }
940
941 if (ilo_dev_gen(dev) >= ILO_GEN(7.5)) {
942 if (memcmp(vf->cut, old->cut, sizeof(vf->cut)))
943 delta->dirty |= ILO_STATE_VF_3DSTATE_VF;
944 } else {
945 if (vf->cut[0] != old->cut[0])
946 delta->dirty |= ILO_STATE_VF_3DSTATE_INDEX_BUFFER;
947 }
948 }
949
950 uint32_t
ilo_state_vertex_buffer_size(const struct ilo_dev * dev,uint32_t size,uint32_t * alignment)951 ilo_state_vertex_buffer_size(const struct ilo_dev *dev, uint32_t size,
952 uint32_t *alignment)
953 {
954 /* align for doubles without padding */
955 *alignment = 8;
956 return size;
957 }
958
959 /**
960 * No need to initialize first.
961 */
962 bool
ilo_state_vertex_buffer_set_info(struct ilo_state_vertex_buffer * vb,const struct ilo_dev * dev,const struct ilo_state_vertex_buffer_info * info)963 ilo_state_vertex_buffer_set_info(struct ilo_state_vertex_buffer *vb,
964 const struct ilo_dev *dev,
965 const struct ilo_state_vertex_buffer_info *info)
966 {
967 bool ret = true;
968
969 ret &= vertex_buffer_set_gen8_vertex_buffer_state(vb, dev, info);
970
971 assert(ret);
972
973 return ret;
974 }
975
976 uint32_t
ilo_state_index_buffer_size(const struct ilo_dev * dev,uint32_t size,uint32_t * alignment)977 ilo_state_index_buffer_size(const struct ilo_dev *dev, uint32_t size,
978 uint32_t *alignment)
979 {
980 /* align for the worst case without padding */
981 *alignment = get_index_format_size(GEN6_INDEX_DWORD);
982 return size;
983 }
984
985 /**
986 * No need to initialize first.
987 */
988 bool
ilo_state_index_buffer_set_info(struct ilo_state_index_buffer * ib,const struct ilo_dev * dev,const struct ilo_state_index_buffer_info * info)989 ilo_state_index_buffer_set_info(struct ilo_state_index_buffer *ib,
990 const struct ilo_dev *dev,
991 const struct ilo_state_index_buffer_info *info)
992 {
993 bool ret = true;
994
995 ret &= index_buffer_set_gen8_3DSTATE_INDEX_BUFFER(ib, dev, info);
996
997 assert(ret);
998
999 return ret;
1000 }
1001