• 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_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