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
;
126 map
= pipe_buffer_map(&nvfx
->pipe
, vb
->buffer
, PIPE_TRANSFER_READ
, &transfer
);
127 map
+= vb
->buffer_offset
+ ve
->src_offset
;
133 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_4F_X(attrib
), 4));
134 OUT_RING(chan
, fui(v
[0]));
135 OUT_RING(chan
, fui(v
[1]));
136 OUT_RING(chan
, fui(v
[2]));
137 OUT_RING(chan
, fui(v
[3]));
140 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_3F_X(attrib
), 3));
141 OUT_RING(chan
, fui(v
[0]));
142 OUT_RING(chan
, fui(v
[1]));
143 OUT_RING(chan
, fui(v
[2]));
146 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_2F_X(attrib
), 2));
147 OUT_RING(chan
, fui(v
[0]));
148 OUT_RING(chan
, fui(v
[1]));
151 OUT_RING(chan
, RING_3D(NV34TCL_VTX_ATTR_1F(attrib
), 1));
152 OUT_RING(chan
, fui(v
[0]));
156 pipe_buffer_unmap(&nvfx
->pipe
, vb
->buffer
, transfer
);
160 nvfx_draw_arrays(struct pipe_context
*pipe
,
161 unsigned mode
, unsigned start
, unsigned count
)
163 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
164 struct nvfx_screen
*screen
= nvfx
->screen
;
165 struct nouveau_channel
*chan
= screen
->base
.channel
;
166 unsigned restart
= 0;
168 nvfx_vbo_set_idxbuf(nvfx
, NULL
, 0);
169 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
170 nvfx_draw_elements_swtnl(pipe
, NULL
, 0, 0,
178 nvfx_state_emit(nvfx
);
180 unsigned avail
= AVAIL_RING(chan
);
181 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
183 vc
= nouveau_vbuf_split(avail
, 6, 256,
184 mode
, start
, count
, &restart
);
190 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
191 OUT_RING (chan
, nvgl_primitive(mode
));
195 OUT_RING(chan
, RING_3D(NV34TCL_VB_VERTEX_BATCH
, 1));
196 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
202 unsigned push
= nr
> 2047 ? 2047 : nr
;
206 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_VERTEX_BATCH
, push
));
208 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
213 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
220 pipe
->flush(pipe
, 0, NULL
);
224 nvfx_draw_elements_u08(struct nvfx_context
*nvfx
, void *ib
,
225 unsigned mode
, unsigned start
, unsigned count
)
227 struct nvfx_screen
*screen
= nvfx
->screen
;
228 struct nouveau_channel
*chan
= screen
->base
.channel
;
231 uint8_t *elts
= (uint8_t *)ib
+ start
;
232 unsigned vc
, push
, restart
= 0;
234 nvfx_state_emit(nvfx
);
236 unsigned avail
= AVAIL_RING(chan
);
237 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
239 vc
= nouveau_vbuf_split(avail
, 6, 2,
240 mode
, start
, count
, &restart
);
247 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
248 OUT_RING (chan
, nvgl_primitive(mode
));
251 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
252 OUT_RING (chan
, elts
[0]);
259 push
= MIN2(vc
, 2047 * 2);
261 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
262 for (i
= 0; i
< push
; i
+=2)
263 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
269 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
277 nvfx_draw_elements_u16(struct nvfx_context
*nvfx
, void *ib
,
278 unsigned mode
, unsigned start
, unsigned count
)
280 struct nvfx_screen
*screen
= nvfx
->screen
;
281 struct nouveau_channel
*chan
= screen
->base
.channel
;
284 uint16_t *elts
= (uint16_t *)ib
+ start
;
285 unsigned vc
, push
, restart
= 0;
287 nvfx_state_emit(nvfx
);
289 unsigned avail
= AVAIL_RING(chan
);
290 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
292 vc
= nouveau_vbuf_split(avail
, 6, 2,
293 mode
, start
, count
, &restart
);
300 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
301 OUT_RING (chan
, nvgl_primitive(mode
));
304 OUT_RING(chan
, RING_3D(NV34TCL_VB_ELEMENT_U32
, 1));
305 OUT_RING (chan
, elts
[0]);
312 push
= MIN2(vc
, 2047 * 2);
314 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U16
, push
>> 1));
315 for (i
= 0; i
< push
; i
+=2)
316 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
322 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
330 nvfx_draw_elements_u32(struct nvfx_context
*nvfx
, void *ib
,
331 unsigned mode
, unsigned start
, unsigned count
)
333 struct nvfx_screen
*screen
= nvfx
->screen
;
334 struct nouveau_channel
*chan
= screen
->base
.channel
;
337 uint32_t *elts
= (uint32_t *)ib
+ start
;
338 unsigned vc
, push
, restart
= 0;
340 nvfx_state_emit(nvfx
);
342 unsigned avail
= AVAIL_RING(chan
);
343 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
345 vc
= nouveau_vbuf_split(avail
, 5, 1,
346 mode
, start
, count
, &restart
);
353 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
354 OUT_RING (chan
, nvgl_primitive(mode
));
357 push
= MIN2(vc
, 2047);
359 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_ELEMENT_U32
, push
));
360 OUT_RINGp (chan
, elts
, push
);
366 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
374 nvfx_draw_elements_inline(struct pipe_context
*pipe
,
375 struct pipe_resource
*ib
,
376 unsigned ib_size
, int ib_bias
,
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");
389 assert(ib_bias
== 0);
393 nvfx_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
396 nvfx_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
399 nvfx_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
402 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
406 pipe_buffer_unmap(pipe
, ib
, transfer
);
410 nvfx_draw_elements_vbo(struct pipe_context
*pipe
,
411 unsigned mode
, unsigned start
, unsigned count
)
413 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
414 struct nvfx_screen
*screen
= nvfx
->screen
;
415 struct nouveau_channel
*chan
= screen
->base
.channel
;
416 unsigned restart
= 0;
421 nvfx_state_emit(nvfx
);
423 unsigned avail
= AVAIL_RING(chan
);
424 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
426 vc
= nouveau_vbuf_split(avail
, 6, 256,
427 mode
, start
, count
, &restart
);
433 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
434 OUT_RING (chan
, nvgl_primitive(mode
));
438 OUT_RING(chan
, RING_3D(NV34TCL_VB_INDEX_BATCH
, 1));
439 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
445 unsigned push
= nr
> 2047 ? 2047 : nr
;
449 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_INDEX_BATCH
, push
));
451 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
456 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
465 nvfx_draw_elements(struct pipe_context
*pipe
,
466 struct pipe_resource
*indexBuffer
,
467 unsigned indexSize
, int indexBias
,
468 unsigned mode
, unsigned start
, unsigned count
)
470 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
473 idxbuf
= nvfx_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
474 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
)) {
475 nvfx_draw_elements_swtnl(pipe
,
476 indexBuffer
, indexSize
, indexBias
,
482 nvfx_draw_elements_vbo(pipe
, mode
, start
, count
);
484 nvfx_draw_elements_inline(pipe
,
485 indexBuffer
, indexSize
, indexBias
,
489 pipe
->flush(pipe
, 0, NULL
);
493 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
495 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
496 struct pipe_resource
*ib
= nvfx
->idxbuf
;
497 unsigned ib_format
= nvfx
->idxbuf_format
;
499 int elements
= MAX2(nvfx
->vtxelt
->num_elements
, nvfx
->hw_vtxelt_nr
);
501 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
;
508 MARK_RING(chan
, (5 + 2) * 16 + 2 + 11, 16 + 2);
509 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
510 struct pipe_vertex_element
*ve
;
511 struct pipe_vertex_buffer
*vb
;
512 unsigned type
, ncomp
;
514 ve
= &nvfx
->vtxelt
->pipe
[i
];
515 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
517 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
519 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
523 if (!vb
->stride
&& type
== NV34TCL_VTXFMT_TYPE_FLOAT
) {
524 nvfx_vbo_static_attrib(nvfx
, i
, ve
, vb
, ncomp
);
527 vtxfmt
[i
] = ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
528 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
);
529 nvfx
->vbo_bo
|= (1 << i
);
533 for(; i
< elements
; ++i
)
534 vtxfmt
[i
] = NV34TCL_VTXFMT_TYPE_FLOAT
;
536 OUT_RING(chan
, RING_3D(NV34TCL_VTXFMT(0), elements
));
537 OUT_RINGp(chan
, vtxfmt
, elements
);
541 /* seems to be some kind of cache flushing */
542 for(i
= 0; i
< 3; ++i
) {
543 OUT_RING(chan
, RING_3D(0x1718, 1));
548 OUT_RING(chan
, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements
));
549 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
550 struct pipe_vertex_element
*ve
;
551 struct pipe_vertex_buffer
*vb
;
553 ve
= &nvfx
->vtxelt
->pipe
[i
];
554 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
556 if (!(nvfx
->vbo_bo
& (1 << i
)))
560 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
562 vb
->buffer_offset
+ ve
->src_offset
,
563 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
564 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
568 for (; i
< elements
; i
++)
571 OUT_RING(chan
, RING_3D(0x1710, 1));
575 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
;
576 struct nouveau_bo
* bo
= nvfx_resource(ib
)->bo
;
578 assert(nvfx
->screen
->index_buffer_reloc_flags
);
580 OUT_RING(chan
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2));
581 OUT_RELOC(chan
, bo
, 0, ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
582 OUT_RELOC(chan
, bo
, ib_format
, ib_flags
| NOUVEAU_BO_OR
,
583 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
586 nvfx
->hw_vtxelt_nr
= nvfx
->vtxelt
->num_elements
;
591 nvfx_vbo_relocate(struct nvfx_context
*nvfx
)
593 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
594 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
597 MARK_RING(chan
, 2 * 16 + 3, 2 * 16 + 3);
598 for(i
= 0; i
< nvfx
->vtxelt
->num_elements
; ++i
) {
599 if(nvfx
->vbo_bo
& (1 << i
)) {
600 struct pipe_vertex_element
*ve
= &nvfx
->vtxelt
->pipe
[i
];
601 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
602 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
603 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_VTXBUF_ADDRESS(i
), 1),
605 OUT_RELOC(chan
, bo
, vb
->buffer_offset
+ ve
->src_offset
,
606 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
607 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
613 unsigned ib_flags
= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
614 struct nouveau_bo
* bo
= nvfx_resource(nvfx
->idxbuf
)->bo
;
616 assert(nvfx
->screen
->index_buffer_reloc_flags
);
618 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2),
620 OUT_RELOC(chan
, bo
, 0,
621 ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
622 OUT_RELOC(chan
, bo
, nvfx
->idxbuf_format
,
623 ib_flags
| NOUVEAU_BO_OR
,
624 0, NV34TCL_IDXBUF_FORMAT_DMA1
);