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_force_swtnl(struct nvfx_context
*nvfx
)
17 static int force_swtnl
= -1;
19 force_swtnl
= debug_get_bool_option("NOUVEAU_SWTNL", 0);
24 nvfx_vbo_format_to_hw(enum pipe_format pipe
, unsigned *fmt
, unsigned *ncomp
)
27 case PIPE_FORMAT_R32_FLOAT
:
28 case PIPE_FORMAT_R32G32_FLOAT
:
29 case PIPE_FORMAT_R32G32B32_FLOAT
:
30 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
31 *fmt
= NV34TCL_VTXFMT_TYPE_FLOAT
;
33 case PIPE_FORMAT_R8_UNORM
:
34 case PIPE_FORMAT_R8G8_UNORM
:
35 case PIPE_FORMAT_R8G8B8_UNORM
:
36 case PIPE_FORMAT_R8G8B8A8_UNORM
:
37 *fmt
= NV34TCL_VTXFMT_TYPE_UBYTE
;
39 case PIPE_FORMAT_R16_SSCALED
:
40 case PIPE_FORMAT_R16G16_SSCALED
:
41 case PIPE_FORMAT_R16G16B16_SSCALED
:
42 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
43 *fmt
= NV34TCL_VTXFMT_TYPE_USHORT
;
46 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
51 case PIPE_FORMAT_R8_UNORM
:
52 case PIPE_FORMAT_R32_FLOAT
:
53 case PIPE_FORMAT_R16_SSCALED
:
56 case PIPE_FORMAT_R8G8_UNORM
:
57 case PIPE_FORMAT_R32G32_FLOAT
:
58 case PIPE_FORMAT_R16G16_SSCALED
:
61 case PIPE_FORMAT_R8G8B8_UNORM
:
62 case PIPE_FORMAT_R32G32B32_FLOAT
:
63 case PIPE_FORMAT_R16G16B16_SSCALED
:
66 case PIPE_FORMAT_R8G8B8A8_UNORM
:
67 case PIPE_FORMAT_R32G32B32A32_FLOAT
:
68 case PIPE_FORMAT_R16G16B16A16_SSCALED
:
72 NOUVEAU_ERR("Unknown format %s\n", util_format_name(pipe
));
80 nvfx_vbo_set_idxbuf(struct nvfx_context
*nvfx
, struct pipe_resource
*ib
,
83 struct pipe_screen
*pscreen
= &nvfx
->screen
->base
.base
;
88 nvfx
->idxbuf_format
= 0xdeadbeef;
92 if (!pscreen
->get_param(pscreen
, NOUVEAU_CAP_HW_IDXBUF
) || 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_force_swtnl(nvfx
) || !nvfx_state_validate(nvfx
)) {
170 nvfx_draw_elements_swtnl(pipe
, NULL
, 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
, unsigned ib_size
,
376 unsigned mode
, unsigned start
, unsigned count
)
378 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
379 struct pipe_transfer
*transfer
;
382 map
= pipe_buffer_map(pipe
, ib
, PIPE_TRANSFER_READ
, &transfer
);
384 NOUVEAU_ERR("failed mapping ib\n");
390 nvfx_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
393 nvfx_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
396 nvfx_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
399 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
403 pipe_buffer_unmap(pipe
, ib
, transfer
);
407 nvfx_draw_elements_vbo(struct pipe_context
*pipe
,
408 unsigned mode
, unsigned start
, unsigned count
)
410 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
411 struct nvfx_screen
*screen
= nvfx
->screen
;
412 struct nouveau_channel
*chan
= screen
->base
.channel
;
413 unsigned restart
= 0;
418 nvfx_state_emit(nvfx
);
420 unsigned avail
= AVAIL_RING(chan
);
421 avail
-= 16 + (avail
>> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */
423 vc
= nouveau_vbuf_split(avail
, 6, 256,
424 mode
, start
, count
, &restart
);
430 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
431 OUT_RING (chan
, nvgl_primitive(mode
));
435 OUT_RING(chan
, RING_3D(NV34TCL_VB_INDEX_BATCH
, 1));
436 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
442 unsigned push
= nr
> 2047 ? 2047 : nr
;
446 OUT_RING(chan
, RING_3D_NI(NV34TCL_VB_INDEX_BATCH
, push
));
448 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
453 OUT_RING(chan
, RING_3D(NV34TCL_VERTEX_BEGIN_END
, 1));
462 nvfx_draw_elements(struct pipe_context
*pipe
,
463 struct pipe_resource
*indexBuffer
, unsigned indexSize
,
464 unsigned mode
, unsigned start
, unsigned count
)
466 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
469 idxbuf
= nvfx_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
470 if (nvfx_force_swtnl(nvfx
) || !nvfx_state_validate(nvfx
)) {
471 nvfx_draw_elements_swtnl(pipe
, indexBuffer
, indexSize
,
477 nvfx_draw_elements_vbo(pipe
, mode
, start
, count
);
479 nvfx_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
483 pipe
->flush(pipe
, 0, NULL
);
487 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
489 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
490 struct pipe_resource
*ib
= nvfx
->idxbuf
;
491 unsigned ib_format
= nvfx
->idxbuf_format
;
493 int elements
= MAX2(nvfx
->vtxelt
->num_elements
, nvfx
->hw_vtxelt_nr
);
494 unsigned long vtxfmt
[16];
495 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_flags
| NOUVEAU_BO_RD
;
502 MARK_RING(chan
, (5 + 2) * 16 + 2 + 11, 16 + 2);
503 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
504 struct pipe_vertex_element
*ve
;
505 struct pipe_vertex_buffer
*vb
;
506 unsigned type
, ncomp
;
508 ve
= &nvfx
->vtxelt
->pipe
[i
];
509 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
511 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
513 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
517 if (!vb
->stride
&& type
== NV34TCL_VTXFMT_TYPE_FLOAT
) {
518 nvfx_vbo_static_attrib(nvfx
, i
, ve
, vb
, ncomp
);
521 vtxfmt
[i
] = ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
522 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
);
523 nvfx
->vbo_bo
|= (1 << i
);
527 for(; i
< elements
; ++i
)
528 vtxfmt
[i
] = NV34TCL_VTXFMT_TYPE_FLOAT
;
530 OUT_RING(chan
, RING_3D(NV34TCL_VTXFMT(0), elements
));
531 OUT_RINGp(chan
, vtxfmt
, elements
);
535 /* seems to be some kind of cache flushing */
536 for(i
= 0; i
< 3; ++i
) {
537 OUT_RING(chan
, RING_3D(0x1718, 1));
542 OUT_RING(chan
, RING_3D(NV34TCL_VTXBUF_ADDRESS(0), elements
));
543 for (i
= 0; i
< nvfx
->vtxelt
->num_elements
; i
++) {
544 struct pipe_vertex_element
*ve
;
545 struct pipe_vertex_buffer
*vb
;
547 ve
= &nvfx
->vtxelt
->pipe
[i
];
548 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
550 if (!(nvfx
->vbo_bo
& (1 << i
)))
554 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
556 vb
->buffer_offset
+ ve
->src_offset
,
557 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
558 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
562 for (; i
< elements
; i
++)
565 OUT_RING(chan
, RING_3D(0x1710, 1));
569 struct nouveau_bo
* bo
= nvfx_resource(ib
)->bo
;
571 OUT_RING(chan
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2));
572 OUT_RELOC(chan
, bo
, 0, vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
573 OUT_RELOC(chan
, bo
, ib_format
, vb_flags
| NOUVEAU_BO_OR
,
574 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
577 nvfx
->hw_vtxelt_nr
= nvfx
->vtxelt
->num_elements
;
581 struct nvfx_state_entry nvfx_state_vbo
= {
582 .validate
= nvfx_vbo_validate
,
584 .pipe
= NVFX_NEW_ARRAYS
,
590 nvfx_vbo_relocate(struct nvfx_context
*nvfx
)
592 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
593 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
596 MARK_RING(chan
, 2 * 16 + 3, 2 * 16 + 3);
597 for(i
= 0; i
< nvfx
->vtxelt
->num_elements
; ++i
) {
598 if(nvfx
->vbo_bo
& (1 << i
)) {
599 struct pipe_vertex_element
*ve
= &nvfx
->vtxelt
->pipe
[i
];
600 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
601 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
602 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_VTXBUF_ADDRESS(i
), 1),
604 OUT_RELOC(chan
, bo
, vb
->buffer_offset
+ ve
->src_offset
,
605 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
606 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
612 struct nouveau_bo
* bo
= nvfx_resource(nvfx
->idxbuf
)->bo
;
614 OUT_RELOC(chan
, bo
, RING_3D(NV34TCL_IDXBUF_ADDRESS
, 2),
616 OUT_RELOC(chan
, bo
, 0,
617 vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
618 OUT_RELOC(chan
, bo
, nvfx
->idxbuf_format
,
619 vb_flags
| NOUVEAU_BO_OR
,
620 0, NV34TCL_IDXBUF_FORMAT_DMA1
);