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 "nv50/nv50_context.h"
9 #include "nv50/nv50_resource.h"
11 #include "nv50/nv50_3d.xml.h"
14 struct nouveau_pushbuf
*push
;
21 uint32_t vertex_words
;
22 uint32_t packet_vertex_limit
;
24 struct translate
*translate
;
26 bool primitive_restart
;
32 uint32_t restart_index
;
36 static inline unsigned
37 prim_restart_search_i08(uint8_t *elts
, unsigned push
, uint8_t index
)
40 for (i
= 0; i
< push
; ++i
)
46 static inline unsigned
47 prim_restart_search_i16(uint16_t *elts
, unsigned push
, uint16_t index
)
50 for (i
= 0; i
< push
; ++i
)
56 static inline unsigned
57 prim_restart_search_i32(uint32_t *elts
, unsigned push
, uint32_t index
)
60 for (i
= 0; i
< push
; ++i
)
67 emit_vertices_i08(struct push_context
*ctx
, unsigned start
, unsigned count
)
69 uint8_t *elts
= (uint8_t *)ctx
->idxbuf
+ start
;
72 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
76 if (ctx
->primitive_restart
)
77 nr
= prim_restart_search_i08(elts
, push
, ctx
->restart_index
);
79 size
= ctx
->vertex_words
* nr
;
81 if (unlikely(ctx
->need_vertex_id
)) {
82 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
83 PUSH_DATA (ctx
->push
, *elts
+ ctx
->index_bias
);
86 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
88 ctx
->translate
->run_elts8(ctx
->translate
, elts
, nr
, 0, ctx
->instance_id
,
91 ctx
->push
->cur
+= size
;
98 BEGIN_NV04(ctx
->push
, NV50_3D(VB_ELEMENT_U32
), 1);
99 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
105 emit_vertices_i16(struct push_context
*ctx
, unsigned start
, unsigned count
)
107 uint16_t *elts
= (uint16_t *)ctx
->idxbuf
+ start
;
110 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
114 if (ctx
->primitive_restart
)
115 nr
= prim_restart_search_i16(elts
, push
, ctx
->restart_index
);
117 size
= ctx
->vertex_words
* nr
;
119 if (unlikely(ctx
->need_vertex_id
)) {
120 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
121 PUSH_DATA (ctx
->push
, *elts
+ ctx
->index_bias
);
124 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
126 ctx
->translate
->run_elts16(ctx
->translate
, elts
, nr
, 0, ctx
->instance_id
,
129 ctx
->push
->cur
+= size
;
136 BEGIN_NV04(ctx
->push
, NV50_3D(VB_ELEMENT_U32
), 1);
137 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
143 emit_vertices_i32(struct push_context
*ctx
, unsigned start
, unsigned count
)
145 uint32_t *elts
= (uint32_t *)ctx
->idxbuf
+ start
;
148 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
152 if (ctx
->primitive_restart
)
153 nr
= prim_restart_search_i32(elts
, push
, ctx
->restart_index
);
155 size
= ctx
->vertex_words
* nr
;
157 if (unlikely(ctx
->need_vertex_id
)) {
158 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
159 PUSH_DATA (ctx
->push
, *elts
+ ctx
->index_bias
);
162 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
164 ctx
->translate
->run_elts(ctx
->translate
, elts
, nr
, 0, ctx
->instance_id
,
167 ctx
->push
->cur
+= size
;
174 BEGIN_NV04(ctx
->push
, NV50_3D(VB_ELEMENT_U32
), 1);
175 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
181 emit_vertices_seq(struct push_context
*ctx
, unsigned start
, unsigned count
)
186 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
187 unsigned size
= ctx
->vertex_words
* push
;
189 if (unlikely(ctx
->need_vertex_id
)) {
190 /* For non-indexed draws, gl_VertexID goes up after each vertex. */
191 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
192 PUSH_DATA (ctx
->push
, elts
++);
195 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
197 ctx
->translate
->run(ctx
->translate
, start
, push
, 0, ctx
->instance_id
,
199 ctx
->push
->cur
+= size
;
206 #define NV50_PRIM_GL_CASE(n) \
207 case PIPE_PRIM_##n: return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
209 static inline unsigned
210 nv50_prim_gl(unsigned prim
)
213 NV50_PRIM_GL_CASE(POINTS
);
214 NV50_PRIM_GL_CASE(LINES
);
215 NV50_PRIM_GL_CASE(LINE_LOOP
);
216 NV50_PRIM_GL_CASE(LINE_STRIP
);
217 NV50_PRIM_GL_CASE(TRIANGLES
);
218 NV50_PRIM_GL_CASE(TRIANGLE_STRIP
);
219 NV50_PRIM_GL_CASE(TRIANGLE_FAN
);
220 NV50_PRIM_GL_CASE(QUADS
);
221 NV50_PRIM_GL_CASE(QUAD_STRIP
);
222 NV50_PRIM_GL_CASE(POLYGON
);
223 NV50_PRIM_GL_CASE(LINES_ADJACENCY
);
224 NV50_PRIM_GL_CASE(LINE_STRIP_ADJACENCY
);
225 NV50_PRIM_GL_CASE(TRIANGLES_ADJACENCY
);
226 NV50_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY
);
228 NV50_PRIM_GL_CASE(PATCHES); */
230 return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS
;
236 nv50_push_vbo(struct nv50_context
*nv50
, const struct pipe_draw_info
*info
)
238 struct push_context ctx
;
239 unsigned i
, index_size
;
240 unsigned inst_count
= info
->instance_count
;
241 unsigned vert_count
= info
->count
;
242 bool apply_bias
= info
->indexed
&& info
->index_bias
;
244 ctx
.push
= nv50
->base
.pushbuf
;
245 ctx
.translate
= nv50
->vertex
->translate
;
247 ctx
.need_vertex_id
= nv50
->screen
->base
.class_3d
>= NV84_3D_CLASS
&&
248 nv50
->vertprog
->vp
.need_vertex_id
&& (nv50
->vertex
->num_elements
< 32);
249 ctx
.index_bias
= info
->index_bias
;
251 /* For indexed draws, gl_VertexID must be emitted for every vertex. */
252 ctx
.packet_vertex_limit
=
253 ctx
.need_vertex_id
? 1 : nv50
->vertex
->packet_vertex_limit
;
254 ctx
.vertex_words
= nv50
->vertex
->vertex_size
;
256 assert(nv50
->num_vtxbufs
<= PIPE_MAX_ATTRIBS
);
257 for (i
= 0; i
< nv50
->num_vtxbufs
; ++i
) {
258 const struct pipe_vertex_buffer
*vb
= &nv50
->vtxbuf
[i
];
261 if (unlikely(vb
->buffer
))
262 data
= nouveau_resource_map_offset(&nv50
->base
,
263 nv04_resource(vb
->buffer
), vb
->buffer_offset
, NOUVEAU_BO_RD
);
265 data
= vb
->user_buffer
;
267 if (apply_bias
&& likely(!(nv50
->vertex
->instance_bufs
& (1 << i
))))
268 data
+= (ptrdiff_t)info
->index_bias
* vb
->stride
;
270 ctx
.translate
->set_buffer(ctx
.translate
, i
, data
, vb
->stride
, ~0);
274 if (nv50
->idxbuf
.buffer
) {
275 ctx
.idxbuf
= nouveau_resource_map_offset(&nv50
->base
,
276 nv04_resource(nv50
->idxbuf
.buffer
), nv50
->idxbuf
.offset
,
279 ctx
.idxbuf
= nv50
->idxbuf
.user_buffer
;
283 index_size
= nv50
->idxbuf
.index_size
;
284 ctx
.primitive_restart
= info
->primitive_restart
;
285 ctx
.restart_index
= info
->restart_index
;
287 if (unlikely(info
->count_from_stream_output
)) {
288 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
289 struct nv50_so_target
*targ
;
290 targ
= nv50_so_target(info
->count_from_stream_output
);
292 NOUVEAU_ERR("draw_stream_output not supported on pre-NVA0 cards\n");
295 pipe
->get_query_result(pipe
, targ
->pq
, true, (void *)&vert_count
);
296 vert_count
/= targ
->stride
;
300 ctx
.primitive_restart
= false;
301 ctx
.restart_index
= 0;
304 ctx
.instance_id
= info
->start_instance
;
305 ctx
.prim
= nv50_prim_gl(info
->mode
);
307 if (info
->primitive_restart
) {
308 BEGIN_NV04(ctx
.push
, NV50_3D(PRIM_RESTART_ENABLE
), 2);
309 PUSH_DATA (ctx
.push
, 1);
310 PUSH_DATA (ctx
.push
, info
->restart_index
);
312 if (nv50
->state
.prim_restart
) {
313 BEGIN_NV04(ctx
.push
, NV50_3D(PRIM_RESTART_ENABLE
), 1);
314 PUSH_DATA (ctx
.push
, 0);
316 nv50
->state
.prim_restart
= info
->primitive_restart
;
318 while (inst_count
--) {
319 BEGIN_NV04(ctx
.push
, NV50_3D(VERTEX_BEGIN_GL
), 1);
320 PUSH_DATA (ctx
.push
, ctx
.prim
);
321 switch (index_size
) {
323 emit_vertices_seq(&ctx
, info
->start
, vert_count
);
326 emit_vertices_i08(&ctx
, info
->start
, vert_count
);
329 emit_vertices_i16(&ctx
, info
->start
, vert_count
);
332 emit_vertices_i32(&ctx
, info
->start
, vert_count
);
338 BEGIN_NV04(ctx
.push
, NV50_3D(VERTEX_END_GL
), 1);
339 PUSH_DATA (ctx
.push
, 0);
342 ctx
.prim
|= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT
;
345 if (unlikely(ctx
.need_vertex_id
)) {
346 /* Reset gl_VertexID to prevent future indexed draws to be confused. */
347 BEGIN_NV04(ctx
.push
, NV84_3D(VERTEX_ID_BASE
), 1);
348 PUSH_DATA (ctx
.push
, nv50
->state
.index_bias
);