2 #include "pipe/p_context.h"
3 #include "pipe/p_state.h"
4 #include "util/u_inlines.h"
5 #include "util/u_format.h"
6 #include "translate/translate.h"
8 #include "nvc0_context.h"
9 #include "nvc0_resource.h"
11 #include "nvc0_3d.xml.h"
14 struct nouveau_pushbuf
*push
;
16 struct translate
*translate
;
21 uint32_t restart_index
;
25 boolean need_vertex_id
;
35 static void nvc0_push_upload_vertex_ids(struct push_context
*,
36 struct nvc0_context
*,
37 const struct pipe_draw_info
*);
40 nvc0_push_context_init(struct nvc0_context
*nvc0
, struct push_context
*ctx
)
42 ctx
->push
= nvc0
->base
.pushbuf
;
44 ctx
->translate
= nvc0
->vertex
->translate
;
45 ctx
->vertex_size
= nvc0
->vertex
->size
;
48 nvc0
->vertprog
->vp
.need_vertex_id
&& (nvc0
->vertex
->num_elements
< 32);
50 ctx
->edgeflag
.value
= TRUE
;
51 ctx
->edgeflag
.enabled
= nvc0
->vertprog
->vp
.edgeflag
< PIPE_MAX_ATTRIBS
;
53 /* silence warnings */
54 ctx
->edgeflag
.data
= NULL
;
55 ctx
->edgeflag
.stride
= 0;
59 nvc0_vertex_configure_translate(struct nvc0_context
*nvc0
, int32_t index_bias
)
61 struct translate
*translate
= nvc0
->vertex
->translate
;
64 for (i
= 0; i
< nvc0
->num_vtxbufs
; ++i
) {
66 const struct pipe_vertex_buffer
*vb
= &nvc0
->vtxbuf
[i
];
68 if (likely(!vb
->buffer
))
69 map
= (const uint8_t *)vb
->user_buffer
;
71 map
= nouveau_resource_map_offset(&nvc0
->base
,
72 nv04_resource(vb
->buffer
), vb
->buffer_offset
, NOUVEAU_BO_RD
);
74 if (index_bias
&& !unlikely(nvc0
->vertex
->instance_bufs
& (1 << i
)))
75 map
+= (intptr_t)index_bias
* vb
->stride
;
77 translate
->set_buffer(translate
, i
, map
, vb
->stride
, ~0);
82 nvc0_push_map_idxbuf(struct push_context
*ctx
, struct nvc0_context
*nvc0
)
84 if (nvc0
->idxbuf
.buffer
) {
85 struct nv04_resource
*buf
= nv04_resource(nvc0
->idxbuf
.buffer
);
86 ctx
->idxbuf
= nouveau_resource_map_offset(&nvc0
->base
,
87 buf
, nvc0
->idxbuf
.offset
, NOUVEAU_BO_RD
);
89 ctx
->idxbuf
= nvc0
->idxbuf
.user_buffer
;
94 nvc0_push_map_edgeflag(struct push_context
*ctx
, struct nvc0_context
*nvc0
,
97 unsigned attr
= nvc0
->vertprog
->vp
.edgeflag
;
98 struct pipe_vertex_element
*ve
= &nvc0
->vertex
->element
[attr
].pipe
;
99 struct pipe_vertex_buffer
*vb
= &nvc0
->vtxbuf
[ve
->vertex_buffer_index
];
100 struct nv04_resource
*buf
= nv04_resource(vb
->buffer
);
101 unsigned offset
= vb
->buffer_offset
+ ve
->src_offset
;
103 ctx
->edgeflag
.stride
= vb
->stride
;
104 ctx
->edgeflag
.data
= nouveau_resource_map_offset(&nvc0
->base
,
105 buf
, offset
, NOUVEAU_BO_RD
);
107 ctx
->edgeflag
.data
+= (intptr_t)index_bias
* vb
->stride
;
110 static INLINE
unsigned
111 prim_restart_search_i08(const uint8_t *elts
, unsigned push
, uint8_t index
)
114 for (i
= 0; i
< push
&& elts
[i
] != index
; ++i
);
118 static INLINE
unsigned
119 prim_restart_search_i16(const uint16_t *elts
, unsigned push
, uint16_t index
)
122 for (i
= 0; i
< push
&& elts
[i
] != index
; ++i
);
126 static INLINE
unsigned
127 prim_restart_search_i32(const uint32_t *elts
, unsigned push
, uint32_t index
)
130 for (i
= 0; i
< push
&& elts
[i
] != index
; ++i
);
134 static INLINE boolean
135 ef_value(const struct push_context
*ctx
, uint32_t index
)
137 float *pf
= (float *)&ctx
->edgeflag
.data
[index
* ctx
->edgeflag
.stride
];
138 return *pf
? TRUE
: FALSE
;
141 static INLINE boolean
142 ef_toggle(struct push_context
*ctx
)
144 ctx
->edgeflag
.value
= !ctx
->edgeflag
.value
;
145 return ctx
->edgeflag
.value
;
148 static INLINE
unsigned
149 ef_toggle_search_i08(struct push_context
*ctx
, const uint8_t *elts
, unsigned n
)
152 for (i
= 0; i
< n
&& ef_value(ctx
, elts
[i
]) == ctx
->edgeflag
.value
; ++i
);
156 static INLINE
unsigned
157 ef_toggle_search_i16(struct push_context
*ctx
, const uint16_t *elts
, unsigned n
)
160 for (i
= 0; i
< n
&& ef_value(ctx
, elts
[i
]) == ctx
->edgeflag
.value
; ++i
);
164 static INLINE
unsigned
165 ef_toggle_search_i32(struct push_context
*ctx
, const uint32_t *elts
, unsigned n
)
168 for (i
= 0; i
< n
&& ef_value(ctx
, elts
[i
]) == ctx
->edgeflag
.value
; ++i
);
172 static INLINE
unsigned
173 ef_toggle_search_seq(struct push_context
*ctx
, unsigned start
, unsigned n
)
176 for (i
= 0; i
< n
&& ef_value(ctx
, start
++) == ctx
->edgeflag
.value
; ++i
);
181 nvc0_push_setup_vertex_array(struct nvc0_context
*nvc0
, const unsigned count
)
183 struct nouveau_pushbuf
*push
= nvc0
->base
.pushbuf
;
184 struct nouveau_bo
*bo
;
186 const unsigned size
= count
* nvc0
->vertex
->size
;
188 void *const dest
= nouveau_scratch_get(&nvc0
->base
, size
, &va
, &bo
);
190 BEGIN_NVC0(push
, NVC0_3D(VERTEX_ARRAY_START_HIGH(0)), 2);
191 PUSH_DATAh(push
, va
);
192 PUSH_DATA (push
, va
);
193 BEGIN_NVC0(push
, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(0)), 2);
194 PUSH_DATAh(push
, va
+ size
- 1);
195 PUSH_DATA (push
, va
+ size
- 1);
197 BCTX_REFN_bo(nvc0
->bufctx_3d
, VTX_TMP
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
,
199 nouveau_pushbuf_validate(push
);
205 disp_vertices_i08(struct push_context
*ctx
, unsigned start
, unsigned count
)
207 struct nouveau_pushbuf
*push
= ctx
->push
;
208 struct translate
*translate
= ctx
->translate
;
209 const uint8_t *restrict elts
= (uint8_t *)ctx
->idxbuf
+ start
;
215 if (unlikely(ctx
->prim_restart
))
216 nR
= prim_restart_search_i08(elts
, nR
, ctx
->restart_index
);
218 translate
->run_elts8(translate
, elts
, nR
, ctx
->instance_id
, ctx
->dest
);
220 ctx
->dest
+= nR
* ctx
->vertex_size
;
225 if (unlikely(ctx
->edgeflag
.enabled
))
226 nE
= ef_toggle_search_i08(ctx
, elts
, nR
);
229 if (likely(nE
>= 2)) {
230 BEGIN_NVC0(push
, NVC0_3D(VERTEX_BUFFER_FIRST
), 2);
231 PUSH_DATA (push
, pos
);
232 PUSH_DATA (push
, nE
);
236 IMMED_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), pos
);
238 BEGIN_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), 1);
239 PUSH_DATA (push
, pos
);
242 if (unlikely(nE
!= nR
))
243 IMMED_NVC0(push
, NVC0_3D(EDGEFLAG
), ef_toggle(ctx
));
250 BEGIN_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), 1);
251 PUSH_DATA (push
, ctx
->restart_index
);
253 ctx
->dest
+= ctx
->vertex_size
;
261 disp_vertices_i16(struct push_context
*ctx
, unsigned start
, unsigned count
)
263 struct nouveau_pushbuf
*push
= ctx
->push
;
264 struct translate
*translate
= ctx
->translate
;
265 const uint16_t *restrict elts
= (uint16_t *)ctx
->idxbuf
+ start
;
271 if (unlikely(ctx
->prim_restart
))
272 nR
= prim_restart_search_i16(elts
, nR
, ctx
->restart_index
);
274 translate
->run_elts16(translate
, elts
, nR
, ctx
->instance_id
, ctx
->dest
);
276 ctx
->dest
+= nR
* ctx
->vertex_size
;
281 if (unlikely(ctx
->edgeflag
.enabled
))
282 nE
= ef_toggle_search_i16(ctx
, elts
, nR
);
285 if (likely(nE
>= 2)) {
286 BEGIN_NVC0(push
, NVC0_3D(VERTEX_BUFFER_FIRST
), 2);
287 PUSH_DATA (push
, pos
);
288 PUSH_DATA (push
, nE
);
292 IMMED_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), pos
);
294 BEGIN_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), 1);
295 PUSH_DATA (push
, pos
);
298 if (unlikely(nE
!= nR
))
299 IMMED_NVC0(push
, NVC0_3D(EDGEFLAG
), ef_toggle(ctx
));
306 BEGIN_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), 1);
307 PUSH_DATA (push
, ctx
->restart_index
);
309 ctx
->dest
+= ctx
->vertex_size
;
317 disp_vertices_i32(struct push_context
*ctx
, unsigned start
, unsigned count
)
319 struct nouveau_pushbuf
*push
= ctx
->push
;
320 struct translate
*translate
= ctx
->translate
;
321 const uint32_t *restrict elts
= (uint32_t *)ctx
->idxbuf
+ start
;
327 if (unlikely(ctx
->prim_restart
))
328 nR
= prim_restart_search_i32(elts
, nR
, ctx
->restart_index
);
330 translate
->run_elts(translate
, elts
, nR
, ctx
->instance_id
, ctx
->dest
);
332 ctx
->dest
+= nR
* ctx
->vertex_size
;
337 if (unlikely(ctx
->edgeflag
.enabled
))
338 nE
= ef_toggle_search_i32(ctx
, elts
, nR
);
341 if (likely(nE
>= 2)) {
342 BEGIN_NVC0(push
, NVC0_3D(VERTEX_BUFFER_FIRST
), 2);
343 PUSH_DATA (push
, pos
);
344 PUSH_DATA (push
, nE
);
348 IMMED_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), pos
);
350 BEGIN_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), 1);
351 PUSH_DATA (push
, pos
);
354 if (unlikely(nE
!= nR
))
355 IMMED_NVC0(push
, NVC0_3D(EDGEFLAG
), ef_toggle(ctx
));
362 BEGIN_NVC0(push
, NVC0_3D(VB_ELEMENT_U32
), 1);
363 PUSH_DATA (push
, ctx
->restart_index
);
365 ctx
->dest
+= ctx
->vertex_size
;
373 disp_vertices_seq(struct push_context
*ctx
, unsigned start
, unsigned count
)
375 struct nouveau_pushbuf
*push
= ctx
->push
;
376 struct translate
*translate
= ctx
->translate
;
379 translate
->run(translate
, start
, count
, ctx
->instance_id
, ctx
->dest
);
383 if (unlikely(ctx
->edgeflag
.enabled
))
384 nr
= ef_toggle_search_seq(ctx
, start
+ pos
, nr
);
388 BEGIN_NVC0(push
, NVC0_3D(VERTEX_BUFFER_FIRST
), 2);
389 PUSH_DATA (push
, pos
);
390 PUSH_DATA (push
, nr
);
392 if (unlikely(nr
!= count
))
393 IMMED_NVC0(push
, NVC0_3D(EDGEFLAG
), ef_toggle(ctx
));
401 #define NVC0_PRIM_GL_CASE(n) \
402 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
404 static INLINE
unsigned
405 nvc0_prim_gl(unsigned prim
)
408 NVC0_PRIM_GL_CASE(POINTS
);
409 NVC0_PRIM_GL_CASE(LINES
);
410 NVC0_PRIM_GL_CASE(LINE_LOOP
);
411 NVC0_PRIM_GL_CASE(LINE_STRIP
);
412 NVC0_PRIM_GL_CASE(TRIANGLES
);
413 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP
);
414 NVC0_PRIM_GL_CASE(TRIANGLE_FAN
);
415 NVC0_PRIM_GL_CASE(QUADS
);
416 NVC0_PRIM_GL_CASE(QUAD_STRIP
);
417 NVC0_PRIM_GL_CASE(POLYGON
);
418 NVC0_PRIM_GL_CASE(LINES_ADJACENCY
);
419 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY
);
420 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY
);
421 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY
);
423 NVC0_PRIM_GL_CASE(PATCHES); */
425 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS
;
430 nvc0_push_vbo(struct nvc0_context
*nvc0
, const struct pipe_draw_info
*info
)
432 struct push_context ctx
;
433 unsigned i
, index_size
;
434 unsigned inst_count
= info
->instance_count
;
435 unsigned vert_count
= info
->count
;
438 nvc0_push_context_init(nvc0
, &ctx
);
440 nvc0_vertex_configure_translate(nvc0
, info
->index_bias
);
442 if (unlikely(ctx
.edgeflag
.enabled
))
443 nvc0_push_map_edgeflag(&ctx
, nvc0
, info
->index_bias
);
445 ctx
.prim_restart
= info
->primitive_restart
;
446 ctx
.restart_index
= info
->restart_index
;
449 nvc0_push_map_idxbuf(&ctx
, nvc0
);
450 index_size
= nvc0
->idxbuf
.index_size
;
452 if (info
->primitive_restart
) {
453 BEGIN_NVC0(ctx
.push
, NVC0_3D(PRIM_RESTART_ENABLE
), 2);
454 PUSH_DATA (ctx
.push
, 1);
455 PUSH_DATA (ctx
.push
, info
->restart_index
);
457 if (nvc0
->state
.prim_restart
) {
458 IMMED_NVC0(ctx
.push
, NVC0_3D(PRIM_RESTART_ENABLE
), 0);
460 nvc0
->state
.prim_restart
= info
->primitive_restart
;
462 if (unlikely(info
->count_from_stream_output
)) {
463 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
464 struct nvc0_so_target
*targ
;
465 targ
= nvc0_so_target(info
->count_from_stream_output
);
466 pipe
->get_query_result(pipe
, targ
->pq
, TRUE
, (void *)&vert_count
);
467 vert_count
/= targ
->stride
;
469 ctx
.idxbuf
= NULL
; /* shut up warnings */
473 ctx
.instance_id
= info
->start_instance
;
475 prim
= nvc0_prim_gl(info
->mode
);
477 PUSH_SPACE(ctx
.push
, 9);
479 ctx
.dest
= nvc0_push_setup_vertex_array(nvc0
, vert_count
);
480 if (unlikely(!ctx
.dest
))
483 if (unlikely(ctx
.need_vertex_id
))
484 nvc0_push_upload_vertex_ids(&ctx
, nvc0
, info
);
486 IMMED_NVC0(ctx
.push
, NVC0_3D(VERTEX_ARRAY_FLUSH
), 0);
487 BEGIN_NVC0(ctx
.push
, NVC0_3D(VERTEX_BEGIN_GL
), 1);
488 PUSH_DATA (ctx
.push
, prim
);
489 switch (index_size
) {
491 disp_vertices_i08(&ctx
, info
->start
, vert_count
);
494 disp_vertices_i16(&ctx
, info
->start
, vert_count
);
497 disp_vertices_i32(&ctx
, info
->start
, vert_count
);
500 assert(index_size
== 0);
501 disp_vertices_seq(&ctx
, info
->start
, vert_count
);
504 PUSH_SPACE(ctx
.push
, 1);
505 IMMED_NVC0(ctx
.push
, NVC0_3D(VERTEX_END_GL
), 0);
508 prim
|= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT
;
511 nouveau_bufctx_reset(nvc0
->bufctx_3d
, NVC0_BIND_VTX_TMP
);
512 nouveau_scratch_done(&nvc0
->base
);
513 } while (inst_count
);
516 /* reset state and unmap buffers (no-op) */
518 if (unlikely(!ctx
.edgeflag
.value
)) {
519 PUSH_SPACE(ctx
.push
, 1);
520 IMMED_NVC0(ctx
.push
, NVC0_3D(EDGEFLAG
), 1);
523 if (unlikely(ctx
.need_vertex_id
)) {
524 PUSH_SPACE(ctx
.push
, 4);
525 IMMED_NVC0(ctx
.push
, NVC0_3D(VERTEX_ID_REPLACE
), 0);
526 BEGIN_NVC0(ctx
.push
, NVC0_3D(VERTEX_ATTRIB_FORMAT(1)), 1);
528 NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST
|
529 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT
|
530 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32
);
531 IMMED_NVC0(ctx
.push
, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 0);
535 nouveau_resource_unmap(nv04_resource(nvc0
->idxbuf
.buffer
));
536 for (i
= 0; i
< nvc0
->num_vtxbufs
; ++i
)
537 nouveau_resource_unmap(nv04_resource(nvc0
->vtxbuf
[i
].buffer
));
541 copy_indices_u8(uint32_t *dst
, const uint8_t *elts
, uint32_t bias
, unsigned n
)
544 for (i
= 0; i
< n
; ++i
)
545 dst
[i
] = elts
[i
] + bias
;
549 copy_indices_u16(uint32_t *dst
, const uint16_t *elts
, uint32_t bias
, unsigned n
)
552 for (i
= 0; i
< n
; ++i
)
553 dst
[i
] = elts
[i
] + bias
;
557 copy_indices_u32(uint32_t *dst
, const uint32_t *elts
, uint32_t bias
, unsigned n
)
560 for (i
= 0; i
< n
; ++i
)
561 dst
[i
] = elts
[i
] + bias
;
565 nvc0_push_upload_vertex_ids(struct push_context
*ctx
,
566 struct nvc0_context
*nvc0
,
567 const struct pipe_draw_info
*info
)
570 struct nouveau_pushbuf
*push
= ctx
->push
;
571 struct nouveau_bo
*bo
;
575 unsigned index_size
= nvc0
->idxbuf
.index_size
;
577 unsigned a
= nvc0
->vertex
->num_elements
;
579 if (!index_size
|| info
->index_bias
)
581 data
= (uint32_t *)nouveau_scratch_get(&nvc0
->base
,
582 info
->count
* index_size
, &va
, &bo
);
584 BCTX_REFN_bo(nvc0
->bufctx_3d
, VTX_TMP
, NOUVEAU_BO_GART
| NOUVEAU_BO_RD
,
586 nouveau_pushbuf_validate(push
);
589 if (!info
->index_bias
) {
590 memcpy(data
, ctx
->idxbuf
, info
->count
* index_size
);
592 switch (nvc0
->idxbuf
.index_size
) {
594 copy_indices_u8(data
, ctx
->idxbuf
, info
->index_bias
, info
->count
);
597 copy_indices_u16(data
, ctx
->idxbuf
, info
->index_bias
, info
->count
);
600 copy_indices_u32(data
, ctx
->idxbuf
, info
->index_bias
, info
->count
);
605 for (i
= 0; i
< info
->count
; ++i
)
606 data
[i
] = i
+ (info
->start
+ info
->index_bias
);
609 format
= (1 << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT
) |
610 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_UINT
;
612 switch (index_size
) {
614 format
|= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_8
;
617 format
|= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_16
;
620 format
|= NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32
;
624 PUSH_SPACE(push
, 12);
626 if (unlikely(nvc0
->state
.instance_elts
& 2)) {
627 nvc0
->state
.instance_elts
&= ~2;
628 IMMED_NVC0(push
, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(1)), 0);
631 BEGIN_NVC0(push
, NVC0_3D(VERTEX_ATTRIB_FORMAT(a
)), 1);
632 PUSH_DATA (push
, format
);
634 BEGIN_NVC0(push
, NVC0_3D(VERTEX_ARRAY_FETCH(1)), 3);
635 PUSH_DATA (push
, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE
| index_size
);
636 PUSH_DATAh(push
, va
);
637 PUSH_DATA (push
, va
);
638 BEGIN_NVC0(push
, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(1)), 2);
639 PUSH_DATAh(push
, va
+ info
->count
* index_size
- 1);
640 PUSH_DATA (push
, va
+ info
->count
* index_size
- 1);
642 #define NVC0_3D_VERTEX_ID_REPLACE_SOURCE_ATTR_X(a) \
643 (((0x80 + (a) * 0x10) / 4) << NVC0_3D_VERTEX_ID_REPLACE_SOURCE__SHIFT)
645 BEGIN_NVC0(push
, NVC0_3D(VERTEX_ID_REPLACE
), 1);
646 PUSH_DATA (push
, NVC0_3D_VERTEX_ID_REPLACE_SOURCE_ATTR_X(a
) | 1);