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
;
117 nvfx_vbo_static_attrib(struct nvfx_context
*nvfx
, struct nouveau_stateobj
*so
,
118 int attrib
, struct pipe_vertex_element
*ve
,
119 struct pipe_vertex_buffer
*vb
)
121 struct pipe_context
*pipe
= &nvfx
->pipe
;
122 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
123 struct pipe_transfer
*transfer
;
124 unsigned type
, ncomp
;
127 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
))
130 map
= pipe_buffer_map(pipe
, vb
->buffer
, PIPE_TRANSFER_READ
, &transfer
);
131 map
+= vb
->buffer_offset
+ ve
->src_offset
;
134 case NV34TCL_VTXFMT_TYPE_FLOAT
:
136 float *v
= (float *)map
;
140 so_method(so
, eng3d
, NV34TCL_VTX_ATTR_4F_X(attrib
), 4);
141 so_data (so
, fui(v
[0]));
142 so_data (so
, fui(v
[1]));
143 so_data (so
, fui(v
[2]));
144 so_data (so
, fui(v
[3]));
147 so_method(so
, eng3d
, NV34TCL_VTX_ATTR_3F_X(attrib
), 3);
148 so_data (so
, fui(v
[0]));
149 so_data (so
, fui(v
[1]));
150 so_data (so
, fui(v
[2]));
153 so_method(so
, eng3d
, NV34TCL_VTX_ATTR_2F_X(attrib
), 2);
154 so_data (so
, fui(v
[0]));
155 so_data (so
, fui(v
[1]));
158 so_method(so
, eng3d
, NV34TCL_VTX_ATTR_1F(attrib
), 1);
159 so_data (so
, fui(v
[0]));
162 pipe_buffer_unmap(pipe
, vb
->buffer
, transfer
);
168 pipe_buffer_unmap(pipe
, vb
->buffer
, transfer
);
172 pipe_buffer_unmap(pipe
, vb
->buffer
, transfer
);
177 nvfx_draw_arrays(struct pipe_context
*pipe
,
178 unsigned mode
, unsigned start
, unsigned count
)
180 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
181 struct nvfx_screen
*screen
= nvfx
->screen
;
182 struct nouveau_channel
*chan
= screen
->base
.channel
;
183 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
184 unsigned restart
= 0;
186 nvfx_vbo_set_idxbuf(nvfx
, NULL
, 0);
187 if (nvfx_force_swtnl(nvfx
) || !nvfx_state_validate(nvfx
)) {
188 nvfx_draw_elements_swtnl(pipe
, NULL
, 0,
196 nvfx_state_emit(nvfx
);
198 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 256,
199 mode
, start
, count
, &restart
);
205 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
206 OUT_RING (chan
, nvgl_primitive(mode
));
210 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_VERTEX_BATCH
, 1);
211 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
217 unsigned push
= nr
> 2047 ? 2047 : nr
;
221 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_VERTEX_BATCH
, push
);
223 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
228 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
235 pipe
->flush(pipe
, 0, NULL
);
239 nvfx_draw_elements_u08(struct nvfx_context
*nvfx
, void *ib
,
240 unsigned mode
, unsigned start
, unsigned count
)
242 struct nvfx_screen
*screen
= nvfx
->screen
;
243 struct nouveau_channel
*chan
= screen
->base
.channel
;
244 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
247 uint8_t *elts
= (uint8_t *)ib
+ start
;
248 unsigned vc
, push
, restart
= 0;
250 nvfx_state_emit(nvfx
);
252 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 2,
253 mode
, start
, count
, &restart
);
260 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
261 OUT_RING (chan
, nvgl_primitive(mode
));
264 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_ELEMENT_U32
, 1);
265 OUT_RING (chan
, elts
[0]);
272 push
= MIN2(vc
, 2047 * 2);
274 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_ELEMENT_U16
, push
>> 1);
275 for (i
= 0; i
< push
; i
+=2)
276 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
282 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
290 nvfx_draw_elements_u16(struct nvfx_context
*nvfx
, void *ib
,
291 unsigned mode
, unsigned start
, unsigned count
)
293 struct nvfx_screen
*screen
= nvfx
->screen
;
294 struct nouveau_channel
*chan
= screen
->base
.channel
;
295 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
298 uint16_t *elts
= (uint16_t *)ib
+ start
;
299 unsigned vc
, push
, restart
= 0;
301 nvfx_state_emit(nvfx
);
303 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 2,
304 mode
, start
, count
, &restart
);
311 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
312 OUT_RING (chan
, nvgl_primitive(mode
));
315 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_ELEMENT_U32
, 1);
316 OUT_RING (chan
, elts
[0]);
323 push
= MIN2(vc
, 2047 * 2);
325 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_ELEMENT_U16
, push
>> 1);
326 for (i
= 0; i
< push
; i
+=2)
327 OUT_RING(chan
, (elts
[i
+1] << 16) | elts
[i
]);
333 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
341 nvfx_draw_elements_u32(struct nvfx_context
*nvfx
, void *ib
,
342 unsigned mode
, unsigned start
, unsigned count
)
344 struct nvfx_screen
*screen
= nvfx
->screen
;
345 struct nouveau_channel
*chan
= screen
->base
.channel
;
346 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
349 uint32_t *elts
= (uint32_t *)ib
+ start
;
350 unsigned vc
, push
, restart
= 0;
352 nvfx_state_emit(nvfx
);
354 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 5, 1,
355 mode
, start
, count
, &restart
);
362 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
363 OUT_RING (chan
, nvgl_primitive(mode
));
366 push
= MIN2(vc
, 2047);
368 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_ELEMENT_U32
, push
);
369 OUT_RINGp (chan
, elts
, push
);
375 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
383 nvfx_draw_elements_inline(struct pipe_context
*pipe
,
384 struct pipe_resource
*ib
, unsigned ib_size
,
385 unsigned mode
, unsigned start
, unsigned count
)
387 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
388 struct pipe_transfer
*transfer
;
391 map
= pipe_buffer_map(pipe
, ib
, PIPE_TRANSFER_READ
, &transfer
);
393 NOUVEAU_ERR("failed mapping ib\n");
399 nvfx_draw_elements_u08(nvfx
, map
, mode
, start
, count
);
402 nvfx_draw_elements_u16(nvfx
, map
, mode
, start
, count
);
405 nvfx_draw_elements_u32(nvfx
, map
, mode
, start
, count
);
408 NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size
);
412 pipe_buffer_unmap(pipe
, ib
, transfer
);
416 nvfx_draw_elements_vbo(struct pipe_context
*pipe
,
417 unsigned mode
, unsigned start
, unsigned count
)
419 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
420 struct nvfx_screen
*screen
= nvfx
->screen
;
421 struct nouveau_channel
*chan
= screen
->base
.channel
;
422 struct nouveau_grobj
*eng3d
= screen
->eng3d
;
423 unsigned restart
= 0;
428 nvfx_state_emit(nvfx
);
430 vc
= nouveau_vbuf_split(AVAIL_RING(chan
), 6, 256,
431 mode
, start
, count
, &restart
);
437 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
438 OUT_RING (chan
, nvgl_primitive(mode
));
442 BEGIN_RING(chan
, eng3d
, NV34TCL_VB_INDEX_BATCH
, 1);
443 OUT_RING (chan
, ((nr
- 1) << 24) | start
);
449 unsigned push
= nr
> 2047 ? 2047 : nr
;
453 BEGIN_RING_NI(chan
, eng3d
, NV34TCL_VB_INDEX_BATCH
, push
);
455 OUT_RING(chan
, ((0x100 - 1) << 24) | start
);
460 BEGIN_RING(chan
, eng3d
, NV34TCL_VERTEX_BEGIN_END
, 1);
469 nvfx_draw_elements(struct pipe_context
*pipe
,
470 struct pipe_resource
*indexBuffer
, unsigned indexSize
,
471 unsigned mode
, unsigned start
, unsigned count
)
473 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
476 idxbuf
= nvfx_vbo_set_idxbuf(nvfx
, indexBuffer
, indexSize
);
477 if (nvfx_force_swtnl(nvfx
) || !nvfx_state_validate(nvfx
)) {
478 nvfx_draw_elements_swtnl(pipe
, indexBuffer
, indexSize
,
484 nvfx_draw_elements_vbo(pipe
, mode
, start
, count
);
486 nvfx_draw_elements_inline(pipe
, indexBuffer
, indexSize
,
490 pipe
->flush(pipe
, 0, NULL
);
494 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
496 struct nouveau_stateobj
*vtxbuf
, *vtxfmt
, *sattr
= NULL
;
497 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
498 struct pipe_resource
*ib
= nvfx
->idxbuf
;
499 unsigned ib_format
= nvfx
->idxbuf_format
;
500 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_flags
| NOUVEAU_BO_RD
;
503 vtxbuf
= so_new(3, 17, 18);
504 so_method(vtxbuf
, eng3d
, NV34TCL_VTXBUF_ADDRESS(0), nvfx
->vtxelt
->num_elements
);
505 vtxfmt
= so_new(1, 16, 0);
506 so_method(vtxfmt
, eng3d
, NV34TCL_VTXFMT(0), nvfx
->vtxelt
->num_elements
);
508 for (hw
= 0; hw
< nvfx
->vtxelt
->num_elements
; hw
++) {
509 struct pipe_vertex_element
*ve
;
510 struct pipe_vertex_buffer
*vb
;
511 unsigned type
, ncomp
;
513 ve
= &nvfx
->vtxelt
->pipe
[hw
];
514 vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
518 sattr
= so_new(16, 16 * 4, 0);
520 if (nvfx_vbo_static_attrib(nvfx
, sattr
, hw
, ve
, vb
)) {
522 so_data(vtxfmt
, NV34TCL_VTXFMT_TYPE_FLOAT
);
527 if (nvfx_vbo_format_to_hw(ve
->src_format
, &type
, &ncomp
)) {
528 nvfx
->fallback_swtnl
|= NVFX_NEW_ARRAYS
;
529 so_ref(NULL
, &vtxbuf
);
530 so_ref(NULL
, &vtxfmt
);
534 so_reloc(vtxbuf
, nvfx_resource(vb
->buffer
)->bo
,
535 vb
->buffer_offset
+ ve
->src_offset
,
536 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
537 0, NV34TCL_VTXBUF_ADDRESS_DMA1
);
538 so_data (vtxfmt
, ((vb
->stride
<< NV34TCL_VTXFMT_STRIDE_SHIFT
) |
539 (ncomp
<< NV34TCL_VTXFMT_SIZE_SHIFT
) | type
));
543 struct nouveau_bo
*bo
= nvfx_resource(ib
)->bo
;
545 so_method(vtxbuf
, eng3d
, NV34TCL_IDXBUF_ADDRESS
, 2);
546 so_reloc (vtxbuf
, bo
, 0, vb_flags
| NOUVEAU_BO_LOW
, 0, 0);
547 so_reloc (vtxbuf
, bo
, ib_format
, vb_flags
| NOUVEAU_BO_OR
,
548 0, NV34TCL_IDXBUF_FORMAT_DMA1
);
551 so_method(vtxbuf
, eng3d
, 0x1710, 1);
554 so_ref(vtxbuf
, &nvfx
->state
.hw
[NVFX_STATE_VTXBUF
]);
555 so_ref(NULL
, &vtxbuf
);
556 nvfx
->state
.dirty
|= (1ULL << NVFX_STATE_VTXBUF
);
557 so_ref(vtxfmt
, &nvfx
->state
.hw
[NVFX_STATE_VTXFMT
]);
558 so_ref(NULL
, &vtxfmt
);
559 nvfx
->state
.dirty
|= (1ULL << NVFX_STATE_VTXFMT
);
560 so_ref(sattr
, &nvfx
->state
.hw
[NVFX_STATE_VTXATTR
]);
561 so_ref(NULL
, &sattr
);
562 nvfx
->state
.dirty
|= (1ULL << NVFX_STATE_VTXATTR
);
566 struct nvfx_state_entry nvfx_state_vbo
= {
567 .validate
= nvfx_vbo_validate
,
569 .pipe
= NVFX_NEW_ARRAYS
,