1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
6 #include "nvfx_context.h"
7 #include "nvfx_state.h"
8 #include "nvfx_resource.h"
10 #include "nouveau/nouveau_channel.h"
11 #include "nouveau/nouveau_pushbuf.h"
12 #include "nouveau/nouveau_util.h"
15 nvfx_vbo_format_to_hw(enum pipe_format pipe
, unsigned *fmt
, unsigned *ncomp
)
18 case PIPE_FORMAT_R32_FLOAT
:
19 case PIPE_FORMAT_R32G32_FLOAT
:
20 case PIPE_FORMAT_R32G32B32_FLOAT
:
21 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
22 *fmt
= NV34TCL_VTXFMT_TYPE_FLOAT
;
24 case PIPE_FORMAT_R16_FLOAT
:
25 case PIPE_FORMAT_R16G16_FLOAT
:
26 case PIPE_FORMAT_R16G16B16_FLOAT
:
27 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
28 *fmt
= NV34TCL_VTXFMT_TYPE_HALF
;
30 case PIPE_FORMAT_R8_UNORM
:
31 case PIPE_FORMAT_R8G8_UNORM
:
32 case PIPE_FORMAT_R8G8B8_UNORM
:
33 case PIPE_FORMAT_R8G8B8A8_UNORM
:
34 *fmt
= NV34TCL_VTXFMT_TYPE_UBYTE
;
36 case PIPE_FORMAT_R16_SSCALED
:
37 case PIPE_FORMAT_R16G16_SSCALED
:
38 case PIPE_FORMAT_R16G16B16_SSCALED
:
39 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
40 *fmt
= NV34TCL_VTXFMT_TYPE_USHORT
;
43 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
48 case PIPE_FORMAT_R8_UNORM
:
49 case PIPE_FORMAT_R32_FLOAT
:
50 case PIPE_FORMAT_R16_FLOAT
:
51 case PIPE_FORMAT_R16_SSCALED
:
54 case PIPE_FORMAT_R8G8_UNORM
:
55 case PIPE_FORMAT_R32G32_FLOAT
:
56 case PIPE_FORMAT_R16G16_FLOAT
:
57 case PIPE_FORMAT_R16G16_SSCALED
:
60 case PIPE_FORMAT_R8G8B8_UNORM
:
61 case PIPE_FORMAT_R32G32B32_FLOAT
:
62 case PIPE_FORMAT_R16G16B16_FLOAT
:
63 case PIPE_FORMAT_R16G16B16_SSCALED
:
66 case PIPE_FORMAT_R8G8B8A8_UNORM
:
67 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
68 case PIPE_FORMAT_R16G16B16A16_FLOAT
:
69 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
73 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
81 nvfx_vbo_set_idxbuf(struct nvfx_context
*nvfx
, struct pipe_resource
*ib
,
88 nvfx
->idxbuf_format
= 0xdeadbeef;
92 if (!nvfx
->screen
->index_buffer_reloc_flags
|| ib_size
== 1)
97 type
= NV34TCL_IDXBUF_FORMAT_TYPE_U16
;
100 type
= NV34TCL_IDXBUF_FORMAT_TYPE_U32
;
106 if (ib
!= nvfx
->idxbuf
||
107 type
!= nvfx
->idxbuf_format
) {
108 nvfx
->dirty
|= NVFX_NEW_ARRAYS
;
110 nvfx
->idxbuf_format
= type
;
116 // type must be floating point
118 nvfx_vbo_static_attrib(struct nvfx_context
*nvfx
,
119 int attrib
, struct pipe_vertex_element
*ve
,
120 struct pipe_vertex_buffer
*vb
, unsigned ncomp
)
122 struct pipe_transfer
*transfer
;
123 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
127 map
= pipe_buffer_map(&nvfx
->pipe
, vb
->buffer
, PIPE_TRANSFER_READ
, &transfer
);
128 map
= (uint8_t *) map
+ vb
->buffer_offset
+ ve
->src_offset
;
134 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_4F_X(attrib
), 4));
135 OUT_RING(chan
, fui(v
[0]));
136 OUT_RING(chan
, fui(v
[1]));
137 OUT_RING(chan
, fui(v
[2]));
138 OUT_RING(chan
, fui(v
[3]));
141 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_3F_X(attrib
), 3));
142 OUT_RING(chan
, fui(v
[0]));
143 OUT_RING(chan
, fui(v
[1]));
144 OUT_RING(chan
, fui(v
[2]));
147 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_2F_X(attrib
), 2));
148 OUT_RING(chan
, fui(v
[0]));
149 OUT_RING(chan
, fui(v
[1]));
152 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_1F(attrib
), 1));
153 OUT_RING(chan
, fui(v
[0]));
157 pipe_buffer_unmap(&nvfx
->pipe
, vb
->buffer
, transfer
);
161 nvfx_draw_arrays(struct pipe_context
*pipe
,
162 unsigned mode
, unsigned start
, unsigned count
)
164 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
165 struct nvfx_screen
*screen
= nvfx
->screen
;
166 struct nouveau_channel
*chan
= screen
->base
.channel
;
167 unsigned restart
= 0;
169 nvfx_vbo_set_idxbuf(nvfx
, NULL
, 0);
170 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
171 nvfx_draw_elements_swtnl(pipe
, NULL
, 0,
177 unsigned vc
, nr
, avail
;
179 nvfx_state_emit(nvfx
);
181 avail
= AVAIL_RING(chan
);
182 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
184 vc
= nouveau_vbuf_split(avail
, 6, 256,
185 mode
, start
, count
, &restart
);
191 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
192 OUT_RING (chan
, nvgl_primitive(mode
));
196 OUT_RING(chan
, RING_3D(NV34TCL_VB_VERTEX_BATCH
, 1));
197 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
203 unsigned push
= nr
> 2047 ? 2047 : nr
;
207 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_VERTEX_BATCH
, push
));
209 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
214 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
221 pipe
->flush(pipe
, 0, NULL
);
225 nvfx_draw_elements_u08(struct nvfx_context
*nvfx
, void *ib
,
226 unsigned mode
, unsigned start
, unsigned count
)
228 struct nvfx_screen
*screen
= nvfx
->screen
;
229 struct nouveau_channel
*chan
= screen
->base
.channel
;
232 uint8_t *elts
= (uint8_t *)ib
+ start
;
233 unsigned vc
, push
, restart
= 0, avail
;
235 nvfx_state_emit(nvfx
);
237 avail
= AVAIL_RING(chan
);
238 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
240 vc
= nouveau_vbuf_split(avail
, 6, 2,
241 mode
, start
, count
, &restart
);
248 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
249 OUT_RING (chan
, nvgl_primitive(mode
));
252 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
253 OUT_RING (chan
, elts
[0]);
260 push
= MIN2(vc
, 2047 * 2);
262 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
263 for (i
= 0; i
< push
; i
+=2)
264 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
270 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
278 nvfx_draw_elements_u16(struct nvfx_context
*nvfx
, void *ib
,
279 unsigned mode
, unsigned start
, unsigned count
)
281 struct nvfx_screen
*screen
= nvfx
->screen
;
282 struct nouveau_channel
*chan
= screen
->base
.channel
;
285 uint16_t *elts
= (uint16_t *)ib
+ start
;
286 unsigned vc
, push
, restart
= 0, avail
;
288 nvfx_state_emit(nvfx
);
290 avail
= AVAIL_RING(chan
);
291 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
293 vc
= nouveau_vbuf_split(avail
, 6, 2,
294 mode
, start
, count
, &restart
);
301 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
302 OUT_RING (chan
, nvgl_primitive(mode
));
305 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
306 OUT_RING (chan
, elts
[0]);
313 push
= MIN2(vc
, 2047 * 2);
315 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
316 for (i
= 0; i
< push
; i
+=2)
317 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
323 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
331 nvfx_draw_elements_u32(struct nvfx_context
*nvfx
, void *ib
,
332 unsigned mode
, unsigned start
, unsigned count
)
334 struct nvfx_screen
*screen
= nvfx
->screen
;
335 struct nouveau_channel
*chan
= screen
->base
.channel
;
338 uint32_t *elts
= (uint32_t *)ib
+ start
;
339 unsigned vc
, push
, restart
= 0, avail
;
341 nvfx_state_emit(nvfx
);
343 avail
= AVAIL_RING(chan
);
344 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
346 vc
= nouveau_vbuf_split(avail
, 5, 1,
347 mode
, start
, count
, &restart
);
354 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
355 OUT_RING (chan
, nvgl_primitive(mode
));
358 push
= MIN2(vc
, 2047);
360 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U32
, push
));
361 OUT_RINGp (chan
, elts
, push
);
367 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
375 nvfx_draw_elements_inline(struct pipe_context
*pipe
,
376 struct pipe_resource
*ib
, unsigned ib_size
,
377 unsigned mode
, unsigned start
, unsigned count
)
379 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
380 struct pipe_transfer
*transfer
;
383 map
= pipe_buffer_map(pipe
, ib
, PIPE_TRANSFER_READ
, &transfer
);
385 NOUVEAU_ERR("failed mapping ib\n");
391 nvfx_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
394 nvfx_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
397 nvfx_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
400 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
404 pipe_buffer_unmap(pipe
, ib
, transfer
);
408 nvfx_draw_elements_vbo(struct pipe_context
*pipe
,
409 unsigned mode
, unsigned start
, unsigned count
)
411 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
412 struct nvfx_screen
*screen
= nvfx
->screen
;
413 struct nouveau_channel
*chan
= screen
->base
.channel
;
414 unsigned restart
= 0;
417 unsigned nr
, vc
, avail
;
419 nvfx_state_emit(nvfx
);
421 avail
= AVAIL_RING(chan
);
422 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
424 vc
= nouveau_vbuf_split(avail
, 6, 256,
425 mode
, start
, count
, &restart
);
431 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
432 OUT_RING (chan
, nvgl_primitive(mode
));
436 OUT_RING(chan
, RING_3D(NV34TCL_VB_INDEX_BATCH
, 1));
437 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
443 unsigned push
= nr
> 2047 ? 2047 : nr
;
447 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_INDEX_BATCH
, push
));
449 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
454 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
463 nvfx_draw_elements(struct pipe_context
*pipe
,
464 struct pipe_resource
*indexBuffer
, unsigned indexSize
,
465 unsigned mode
, unsigned start
, unsigned count
)
467 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
470 idxbuf
= nvfx_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
471 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
472 nvfx_draw_elements_swtnl(pipe
, indexBuffer
, indexSize
,
478 nvfx_draw_elements_vbo(pipe
, mode
, start
, count
);
480 nvfx_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
484 pipe
->flush(pipe
, 0, NULL
);
488 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
490 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
491 struct pipe_resource
*ib
= nvfx
->idxbuf
;
492 unsigned ib_format
= nvfx
->idxbuf_format
;
494 int elements
= MAX2(nvfx
->vtxelt
->num_elements
, nvfx
->hw_vtxelt_nr
);
496 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
;
503 MARK_RING(chan
, (5 + 2) * 16 + 2 + 11, 16 + 2);
504 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
505 struct pipe_vertex_element
*ve
;
506 struct pipe_vertex_buffer
*vb
;
507 unsigned type
, ncomp
;
509 ve
= &nvfx
->vtxelt
->pipe
[i
];
510 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
512 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
514 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
518 if (!vb
->stride
&& type
== NV34TCL_VTXFMT_TYPE_FLOAT
) {
519 nvfx_vbo_static_attrib(nvfx
, i
, ve
, vb
, ncomp
);
522 vtxfmt
[i
] = ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
523 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
);
524 nvfx
->vbo_bo
|= (1 << i
);
528 for(; i
< elements
; ++i
)
529 vtxfmt
[i
] = NV34TCL_VTXFMT_TYPE_FLOAT
;
531 OUT_RING(chan
, RING_3D(NV34TCL_VTXFMT(0), elements
));
532 OUT_RINGp(chan
, vtxfmt
, elements
);
536 /* seems to be some kind of cache flushing */
537 for(i
= 0; i
< 3; ++i
) {
538 OUT_RING(chan
, RING_3D(0x1718, 1));
543 OUT_RING(chan
, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements
));
544 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
545 struct pipe_vertex_element
*ve
;
546 struct pipe_vertex_buffer
*vb
;
548 ve
= &nvfx
->vtxelt
->pipe
[i
];
549 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
551 if (!(nvfx
->vbo_bo
& (1 << i
)))
555 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
557 vb
->buffer_offset
+ ve
->src_offset
,
558 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
559 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
563 for (; i
< elements
; i
++)
566 OUT_RING(chan
, RING_3D(0x1710, 1));
570 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
;
571 struct nouveau_bo
* bo
= nvfx_resource(ib
)->bo
;
573 assert(nvfx
->screen
->index_buffer_reloc_flags
);
575 OUT_RING(chan
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2));
576 OUT_RELOC(chan
, bo
, 0, ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
577 OUT_RELOC(chan
, bo
, ib_format
, ib_flags
| NOUVEAU_BO_OR
,
578 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
581 nvfx
->hw_vtxelt_nr
= nvfx
->vtxelt
->num_elements
;
586 nvfx_vbo_relocate(struct nvfx_context
*nvfx
)
588 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
589 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
592 MARK_RING(chan
, 2 * 16 + 3, 2 * 16 + 3);
593 for(i
= 0; i
< nvfx
->vtxelt
->num_elements
; ++i
) {
594 if(nvfx
->vbo_bo
& (1 << i
)) {
595 struct pipe_vertex_element
*ve
= &nvfx
->vtxelt
->pipe
[i
];
596 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
597 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
598 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_VTXBUF_ADDRESS(i
), 1),
600 OUT_RELOC(chan
, bo
, vb
->buffer_offset
+ ve
->src_offset
,
601 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
602 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
608 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
609 struct nouveau_bo
* bo
= nvfx_resource(nvfx
->idxbuf
)->bo
;
611 assert(nvfx
->screen
->index_buffer_reloc_flags
);
613 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2),
615 OUT_RELOC(chan
, bo
, 0,
616 ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
617 OUT_RELOC(chan
, bo
, nvfx
->idxbuf_format
,
618 ib_flags
| NOUVEAU_BO_OR
,
619 0, NV34TCL_IDXBUF_FORMAT_DMA1
);