2 #include "pipe/p_context.h"
3 #include "pipe/p_state.h"
4 #include "util/u_inlines.h"
5 #include "util/format/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
;
33 uint32_t start_instance
;
37 static inline unsigned
38 prim_restart_search_i08(uint8_t *elts
, unsigned push
, uint8_t index
)
41 for (i
= 0; i
< push
; ++i
)
47 static inline unsigned
48 prim_restart_search_i16(uint16_t *elts
, unsigned push
, uint16_t index
)
51 for (i
= 0; i
< push
; ++i
)
57 static inline unsigned
58 prim_restart_search_i32(uint32_t *elts
, unsigned push
, uint32_t index
)
61 for (i
= 0; i
< push
; ++i
)
68 emit_vertices_i08(struct push_context
*ctx
, unsigned start
, unsigned count
)
70 uint8_t *elts
= (uint8_t *)ctx
->idxbuf
+ start
;
73 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
77 if (ctx
->primitive_restart
)
78 nr
= prim_restart_search_i08(elts
, push
, ctx
->restart_index
);
80 size
= ctx
->vertex_words
* nr
;
82 if (unlikely(ctx
->need_vertex_id
)) {
83 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
84 PUSH_DATA (ctx
->push
, *elts
+ ctx
->index_bias
);
87 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
89 ctx
->translate
->run_elts8(ctx
->translate
, elts
, nr
,
90 ctx
->start_instance
, ctx
->instance_id
,
93 ctx
->push
->cur
+= size
;
100 BEGIN_NV04(ctx
->push
, NV50_3D(VB_ELEMENT_U32
), 1);
101 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
107 emit_vertices_i16(struct push_context
*ctx
, unsigned start
, unsigned count
)
109 uint16_t *elts
= (uint16_t *)ctx
->idxbuf
+ start
;
112 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
116 if (ctx
->primitive_restart
)
117 nr
= prim_restart_search_i16(elts
, push
, ctx
->restart_index
);
119 size
= ctx
->vertex_words
* nr
;
121 if (unlikely(ctx
->need_vertex_id
)) {
122 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
123 PUSH_DATA (ctx
->push
, *elts
+ ctx
->index_bias
);
126 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
128 ctx
->translate
->run_elts16(ctx
->translate
, elts
, nr
,
129 ctx
->start_instance
, ctx
->instance_id
,
132 ctx
->push
->cur
+= size
;
139 BEGIN_NV04(ctx
->push
, NV50_3D(VB_ELEMENT_U32
), 1);
140 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
146 emit_vertices_i32(struct push_context
*ctx
, unsigned start
, unsigned count
)
148 uint32_t *elts
= (uint32_t *)ctx
->idxbuf
+ start
;
151 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
155 if (ctx
->primitive_restart
)
156 nr
= prim_restart_search_i32(elts
, push
, ctx
->restart_index
);
158 size
= ctx
->vertex_words
* nr
;
160 if (unlikely(ctx
->need_vertex_id
)) {
161 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
162 PUSH_DATA (ctx
->push
, *elts
+ ctx
->index_bias
);
165 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
167 ctx
->translate
->run_elts(ctx
->translate
, elts
, nr
,
168 ctx
->start_instance
, ctx
->instance_id
,
171 ctx
->push
->cur
+= size
;
178 BEGIN_NV04(ctx
->push
, NV50_3D(VB_ELEMENT_U32
), 1);
179 PUSH_DATA (ctx
->push
, ctx
->restart_index
);
185 emit_vertices_seq(struct push_context
*ctx
, unsigned start
, unsigned count
)
190 unsigned push
= MIN2(count
, ctx
->packet_vertex_limit
);
191 unsigned size
= ctx
->vertex_words
* push
;
193 if (unlikely(ctx
->need_vertex_id
)) {
194 /* For non-indexed draws, gl_VertexID goes up after each vertex. */
195 BEGIN_NV04(ctx
->push
, NV84_3D(VERTEX_ID_BASE
), 1);
196 PUSH_DATA (ctx
->push
, elts
++);
199 BEGIN_NI04(ctx
->push
, NV50_3D(VERTEX_DATA
), size
);
201 ctx
->translate
->run(ctx
->translate
, start
, push
,
202 ctx
->start_instance
, ctx
->instance_id
,
204 ctx
->push
->cur
+= size
;
211 #define NV50_PRIM_GL_CASE(n) \
212 case PIPE_PRIM_##n: return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n
214 static inline unsigned
215 nv50_prim_gl(unsigned prim
)
218 NV50_PRIM_GL_CASE(POINTS
);
219 NV50_PRIM_GL_CASE(LINES
);
220 NV50_PRIM_GL_CASE(LINE_LOOP
);
221 NV50_PRIM_GL_CASE(LINE_STRIP
);
222 NV50_PRIM_GL_CASE(TRIANGLES
);
223 NV50_PRIM_GL_CASE(TRIANGLE_STRIP
);
224 NV50_PRIM_GL_CASE(TRIANGLE_FAN
);
225 NV50_PRIM_GL_CASE(QUADS
);
226 NV50_PRIM_GL_CASE(QUAD_STRIP
);
227 NV50_PRIM_GL_CASE(POLYGON
);
228 NV50_PRIM_GL_CASE(LINES_ADJACENCY
);
229 NV50_PRIM_GL_CASE(LINE_STRIP_ADJACENCY
);
230 NV50_PRIM_GL_CASE(TRIANGLES_ADJACENCY
);
231 NV50_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY
);
233 NV50_PRIM_GL_CASE(PATCHES); */
235 return NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS
;
241 nv50_push_vbo(struct nv50_context
*nv50
, const struct pipe_draw_info
*info
)
243 struct push_context ctx
;
244 unsigned i
, index_size
;
245 unsigned inst_count
= info
->instance_count
;
246 unsigned vert_count
= info
->count
;
247 bool apply_bias
= info
->index_size
&& info
->index_bias
;
249 ctx
.push
= nv50
->base
.pushbuf
;
250 ctx
.translate
= nv50
->vertex
->translate
;
252 ctx
.need_vertex_id
= nv50
->screen
->base
.class_3d
>= NV84_3D_CLASS
&&
253 nv50
->vertprog
->vp
.need_vertex_id
&& (nv50
->vertex
->num_elements
< 32);
254 ctx
.index_bias
= info
->index_bias
;
257 /* For indexed draws, gl_VertexID must be emitted for every vertex. */
258 ctx
.packet_vertex_limit
=
259 ctx
.need_vertex_id
? 1 : nv50
->vertex
->packet_vertex_limit
;
260 ctx
.vertex_words
= nv50
->vertex
->vertex_size
;
262 assert(nv50
->num_vtxbufs
<= PIPE_MAX_ATTRIBS
);
263 for (i
= 0; i
< nv50
->num_vtxbufs
; ++i
) {
264 const struct pipe_vertex_buffer
*vb
= &nv50
->vtxbuf
[i
];
267 if (unlikely(!vb
->is_user_buffer
)) {
268 if (!vb
->buffer
.resource
)
271 data
= nouveau_resource_map_offset(&nv50
->base
,
272 nv04_resource(vb
->buffer
.resource
), vb
->buffer_offset
, NOUVEAU_BO_RD
);
274 data
= vb
->buffer
.user
;
276 if (apply_bias
&& likely(!(nv50
->vertex
->instance_bufs
& (1 << i
))))
277 data
+= (ptrdiff_t)info
->index_bias
* vb
->stride
;
279 ctx
.translate
->set_buffer(ctx
.translate
, i
, data
, vb
->stride
, ~0);
282 if (info
->index_size
) {
283 if (!info
->has_user_indices
) {
284 ctx
.idxbuf
= nouveau_resource_map_offset(&nv50
->base
,
285 nv04_resource(info
->index
.resource
), 0, NOUVEAU_BO_RD
);
287 ctx
.idxbuf
= info
->index
.user
;
291 index_size
= info
->index_size
;
292 ctx
.primitive_restart
= info
->primitive_restart
;
293 ctx
.restart_index
= info
->restart_index
;
295 if (unlikely(info
->count_from_stream_output
)) {
296 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
297 struct nv50_so_target
*targ
;
298 targ
= nv50_so_target(info
->count_from_stream_output
);
300 NOUVEAU_ERR("draw_stream_output not supported on pre-NVA0 cards\n");
303 pipe
->get_query_result(pipe
, targ
->pq
, true, (void *)&vert_count
);
304 vert_count
/= targ
->stride
;
308 ctx
.primitive_restart
= false;
309 ctx
.restart_index
= 0;
312 ctx
.start_instance
= info
->start_instance
;
313 ctx
.prim
= nv50_prim_gl(info
->mode
);
315 if (info
->primitive_restart
) {
316 BEGIN_NV04(ctx
.push
, NV50_3D(PRIM_RESTART_ENABLE
), 2);
317 PUSH_DATA (ctx
.push
, 1);
318 PUSH_DATA (ctx
.push
, info
->restart_index
);
320 if (nv50
->state
.prim_restart
) {
321 BEGIN_NV04(ctx
.push
, NV50_3D(PRIM_RESTART_ENABLE
), 1);
322 PUSH_DATA (ctx
.push
, 0);
324 nv50
->state
.prim_restart
= info
->primitive_restart
;
326 while (inst_count
--) {
327 BEGIN_NV04(ctx
.push
, NV50_3D(VERTEX_BEGIN_GL
), 1);
328 PUSH_DATA (ctx
.push
, ctx
.prim
);
329 switch (index_size
) {
331 emit_vertices_seq(&ctx
, info
->start
, vert_count
);
334 emit_vertices_i08(&ctx
, info
->start
, vert_count
);
337 emit_vertices_i16(&ctx
, info
->start
, vert_count
);
340 emit_vertices_i32(&ctx
, info
->start
, vert_count
);
346 BEGIN_NV04(ctx
.push
, NV50_3D(VERTEX_END_GL
), 1);
347 PUSH_DATA (ctx
.push
, 0);
350 ctx
.prim
|= NV50_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT
;
353 if (unlikely(ctx
.need_vertex_id
)) {
354 /* Reset gl_VertexID to prevent future indexed draws to be confused. */
355 BEGIN_NV04(ctx
.push
, NV84_3D(VERTEX_ID_BASE
), 1);
356 PUSH_DATA (ctx
.push
, nv50
->state
.index_bias
);