1 #include "pipe/p_context.h"
2 #include "pipe/p_state.h"
3 #include "util/u_inlines.h"
4 #include "util/u_format.h"
5 #include "util/u_transfer.h"
6 #include "translate/translate.h"
8 #include "nvfx_context.h"
9 #include "nvfx_state.h"
10 #include "nvfx_resource.h"
12 #include "nouveau/nouveau_channel.h"
13 #include "nouveau/nv04_pushbuf.h"
15 static inline unsigned
16 util_guess_unique_indices_count(unsigned mode
, unsigned indices
)
18 /* Euler's formula gives V =
20 * = F * (polygon_edges / 2 - 1) + 2 =
21 * = F * (polygon_edges - 2) / 2 + 2 =
22 * = indices * (polygon_edges - 2) / (2 * indices_per_face) + 2
23 * = indices * (1 / 2 - 1 / polygon_edges) + 2
29 case PIPE_PRIM_TRIANGLES
:
31 // avoid an expensive division by 3 using the multiplicative inverse mod 2^32
33 unsigned inv3
= 2863311531;
36 if(unlikely(q
>= indices
))
43 //return indices / 6 + 2;
45 // guess that indexed quads are created by successive connections, since a closed mesh seems unlikely
47 return (indices
>> 1) + 2;
48 // return (indices >> 2) + 2; // if it is a closed mesh
54 static unsigned nvfx_decide_upload_mode(struct pipe_context
*pipe
, const struct pipe_draw_info
*info
)
56 struct nvfx_context
* nvfx
= nvfx_context(pipe
);
57 unsigned hardware_cost
= 0;
58 unsigned inline_cost
= 0;
59 unsigned unique_vertices
;
61 float best_index_cost_for_hardware_vertices_as_inline_cost
;
62 boolean prefer_hardware_indices
;
63 unsigned index_inline_cost
;
64 unsigned index_hardware_cost
;
66 unique_vertices
= util_guess_unique_indices_count(info
->mode
, info
->count
);
68 unique_vertices
= info
->count
;
70 /* Here we try to figure out if we are better off writing vertex data directly on the FIFO,
71 * or create hardware buffer objects and pointing the hardware to them.
73 * This is done by computing the total memcpy cost of each option, ignoring uploads
74 * if we think that the buffer is static and thus the upload cost will be amortized over
77 * For instance, if everything looks static, we will always create buffer objects, while if
78 * everything is a user buffer and we are not doing indexed drawing, we never do.
80 * Other interesting cases are where a small user vertex buffer, but a huge user index buffer,
81 * where we will upload the vertex buffer, so that we can use hardware index lookup, and
82 * the opposite case, where we instead do index lookup in software to avoid uploading
83 * a huge amount of vertex data that is not going to be used.
85 * Otherwise, we generally move to the GPU the after it has been pushed
86 * NVFX_STATIC_BUFFER_MIN_REUSE_TIMES times to the GPU without having
87 * been updated with a transfer (or just the buffer having been destroyed).
89 * There is no special handling for user buffers, since applications can use
90 * OpenGL VBOs in a one-shot fashion. OpenGL 3/4 core profile forces this
93 * Note that currently we don't support only putting some data on the FIFO, and
94 * some on vertex buffers (constant and instanced data is independent from this).
96 * nVidia doesn't seem to do this either, even though it should be at least
97 * doable with VTX_ATTR and possibly with VERTEX_DATA too if not indexed.
100 for (unsigned i
= 0; i
< nvfx
->vtxelt
->num_per_vertex_buffer_infos
; i
++)
102 struct nvfx_per_vertex_buffer_info
* vbi
= &nvfx
->vtxelt
->per_vertex_buffer_info
[i
];
103 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[vbi
->vertex_buffer_index
];
104 struct nvfx_buffer
* buffer
= nvfx_buffer(vb
->buffer
);
105 buffer
->bytes_to_draw_until_static
-= vbi
->per_vertex_size
* unique_vertices
;
106 if (!nvfx_buffer_seems_static(buffer
))
108 hardware_cost
+= buffer
->dirty_end
- buffer
->dirty_begin
;
109 if (!buffer
->base
.bo
)
110 hardware_cost
+= nvfx
->screen
->buffer_allocation_cost
;
112 inline_cost
+= vbi
->per_vertex_size
* info
->count
;
115 best_index_cost_for_hardware_vertices_as_inline_cost
= 0.0f
;
116 prefer_hardware_indices
= FALSE
;
117 index_inline_cost
= 0;
118 index_hardware_cost
= 0;
122 index_inline_cost
= nvfx
->idxbuf
.index_size
* info
->count
;
123 if (nvfx
->screen
->index_buffer_reloc_flags
124 && (nvfx
->idxbuf
.index_size
== 2 || nvfx
->idxbuf
.index_size
== 4)
125 && !(nvfx
->idxbuf
.offset
& (nvfx
->idxbuf
.index_size
- 1)))
127 struct nvfx_buffer
* buffer
= nvfx_buffer(nvfx
->idxbuf
.buffer
);
128 buffer
->bytes_to_draw_until_static
-= index_inline_cost
;
130 prefer_hardware_indices
= TRUE
;
132 if (!nvfx_buffer_seems_static(buffer
))
134 index_hardware_cost
= buffer
->dirty_end
- buffer
->dirty_begin
;
135 if (!buffer
->base
.bo
)
136 index_hardware_cost
+= nvfx
->screen
->buffer_allocation_cost
;
139 if ((float) index_inline_cost
< (float) index_hardware_cost
* nvfx
->screen
->inline_cost_per_hardware_cost
)
141 best_index_cost_for_hardware_vertices_as_inline_cost
= (float) index_inline_cost
;
145 best_index_cost_for_hardware_vertices_as_inline_cost
= (float) index_hardware_cost
* nvfx
->screen
->inline_cost_per_hardware_cost
;
146 prefer_hardware_indices
= TRUE
;
151 /* let's finally figure out which of the 3 paths we want to take */
152 if ((float) (inline_cost
+ index_inline_cost
) > ((float) hardware_cost
* nvfx
->screen
->inline_cost_per_hardware_cost
+ best_index_cost_for_hardware_vertices_as_inline_cost
))
153 upload_mode
= 1 + prefer_hardware_indices
;
158 if (unlikely(nvfx
->screen
->trace_draw
))
160 fprintf(stderr
, "DRAW");
163 fprintf(stderr
, "_IDX%u", nvfx
->idxbuf
.index_size
);
164 if (info
->index_bias
)
165 fprintf(stderr
, " biased %u", info
->index_bias
);
166 fprintf(stderr
, " idxrange %u -> %u", info
->min_index
, info
->max_index
);
168 if (info
->instance_count
> 1)
169 fprintf(stderr
, " %u instances from %u", info
->instance_count
, info
->indexed
);
170 fprintf(stderr
, " start %u count %u prim %u", info
->start
, info
->count
, info
->mode
);
172 fprintf(stderr
, " -> inline vertex data");
173 else if (upload_mode
== 2 || !info
->indexed
)
174 fprintf(stderr
, " -> buffer range");
176 fprintf(stderr
, " -> inline indices");
177 fprintf(stderr
, " [ivtx %u hvtx %u iidx %u hidx %u bidx %f] <", inline_cost
, hardware_cost
, index_inline_cost
, index_hardware_cost
, best_index_cost_for_hardware_vertices_as_inline_cost
);
178 for (unsigned i
= 0; i
< nvfx
->vtxelt
->num_per_vertex_buffer_infos
; ++i
)
180 struct nvfx_per_vertex_buffer_info
* vbi
= &nvfx
->vtxelt
->per_vertex_buffer_info
[i
];
181 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[vbi
->vertex_buffer_index
];
182 struct nvfx_buffer
* buffer
= nvfx_buffer(vb
->buffer
);
184 fprintf(stderr
, ", ");
185 fprintf(stderr
, "%p%s left %Li", buffer
, buffer
->last_update_static
? " static" : "", buffer
->bytes_to_draw_until_static
);
187 fprintf(stderr
, ">\n");
194 void nvfx_draw_vbo(struct pipe_context
*pipe
, const struct pipe_draw_info
*info
)
196 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
197 unsigned upload_mode
= 0;
199 if (!nvfx
->vtxelt
->needs_translate
)
200 upload_mode
= nvfx_decide_upload_mode(pipe
, info
);
202 nvfx
->use_index_buffer
= upload_mode
> 1;
204 if ((upload_mode
> 0) != nvfx
->use_vertex_buffers
)
206 nvfx
->use_vertex_buffers
= (upload_mode
> 0);
207 nvfx
->dirty
|= NVFX_NEW_ARRAYS
;
208 nvfx
->draw_dirty
|= NVFX_NEW_ARRAYS
;
213 for (unsigned i
= 0; i
< nvfx
->vtxelt
->num_per_vertex_buffer_infos
; i
++)
215 struct nvfx_per_vertex_buffer_info
* vbi
= &nvfx
->vtxelt
->per_vertex_buffer_info
[i
];
216 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[vbi
->vertex_buffer_index
];
217 nvfx_buffer_upload(nvfx_buffer(vb
->buffer
));
222 nvfx_buffer_upload(nvfx_buffer(nvfx
->idxbuf
.buffer
));
224 if (unlikely(info
->index_bias
!= nvfx
->base_vertex
))
226 nvfx
->base_vertex
= info
->index_bias
;
227 nvfx
->dirty
|= NVFX_NEW_ARRAYS
;
232 if (unlikely(info
->start
< nvfx
->base_vertex
&& nvfx
->base_vertex
))
234 nvfx
->base_vertex
= 0;
235 nvfx
->dirty
|= NVFX_NEW_ARRAYS
;
240 if (nvfx
->screen
->force_swtnl
|| !nvfx_state_validate(nvfx
))
241 nvfx_draw_vbo_swtnl(pipe
, info
);
243 nvfx_push_vbo(pipe
, info
);
247 nvfx_vbo_validate(struct nvfx_context
*nvfx
)
249 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
250 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
252 int elements
= MAX2(nvfx
->vtxelt
->num_elements
, nvfx
->hw_vtxelt_nr
);
253 unsigned vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
;
258 MARK_RING(chan
, (5 + 2) * 16 + 2 + 11, 16 + 2);
259 for(unsigned i
= 0; i
< nvfx
->vtxelt
->num_constant
; ++i
)
261 struct nvfx_low_frequency_element
*ve
= &nvfx
->vtxelt
->constant
[i
];
262 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
263 struct nvfx_buffer
* buffer
= nvfx_buffer(vb
->buffer
);
265 ve
->fetch_rgba_float(v
, buffer
->data
+ vb
->buffer_offset
+ ve
->src_offset
, 0, 0);
266 nvfx_emit_vtx_attr(chan
, eng3d
, ve
->idx
, v
, ve
->ncomp
);
270 BEGIN_RING(chan
, eng3d
, NV30_3D_VTXFMT(0), elements
);
271 if(nvfx
->use_vertex_buffers
)
274 for (i
= 0; i
< nvfx
->vtxelt
->num_per_vertex
; i
++) {
275 struct nvfx_per_vertex_element
*ve
= &nvfx
->vtxelt
->per_vertex
[i
];
276 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
280 assert(idx
< ve
->idx
);
281 OUT_RINGp(chan
, &nvfx
->vtxelt
->vtxfmt
[idx
], ve
->idx
- idx
);
285 OUT_RING(chan
, nvfx
->vtxelt
->vtxfmt
[idx
] | (vb
->stride
<< NV30_3D_VTXFMT_STRIDE__SHIFT
));
288 if(idx
!= nvfx
->vtxelt
->num_elements
)
289 OUT_RINGp(chan
, &nvfx
->vtxelt
->vtxfmt
[idx
], nvfx
->vtxelt
->num_elements
- idx
);
292 OUT_RINGp(chan
, nvfx
->vtxelt
->vtxfmt
, nvfx
->vtxelt
->num_elements
);
294 for(i
= nvfx
->vtxelt
->num_elements
; i
< elements
; ++i
)
295 OUT_RING(chan
, NV30_3D_VTXFMT_TYPE_V32_FLOAT
);
299 /* seems to be some kind of cache flushing */
300 for(i
= 0; i
< 3; ++i
) {
301 BEGIN_RING(chan
, eng3d
, 0x1718, 1);
306 BEGIN_RING(chan
, eng3d
, NV30_3D_VTXBUF(0), elements
);
307 if(nvfx
->use_vertex_buffers
)
310 for (i
= 0; i
< nvfx
->vtxelt
->num_per_vertex
; i
++) {
311 struct nvfx_per_vertex_element
*ve
= &nvfx
->vtxelt
->per_vertex
[i
];
312 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
313 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
315 for(; idx
< ve
->idx
; ++idx
)
319 vb
->buffer_offset
+ ve
->src_offset
+ nvfx
->base_vertex
* vb
->stride
,
320 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
321 0, NV30_3D_VTXBUF_DMA1
);
325 for(; idx
< elements
; ++idx
)
330 for (i
= 0; i
< elements
; i
++)
334 BEGIN_RING(chan
, eng3d
, 0x1710, 1);
337 nvfx
->hw_vtxelt_nr
= nvfx
->vtxelt
->num_elements
;
338 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_VTXBUF
;
343 nvfx_vbo_swtnl_validate(struct nvfx_context
*nvfx
)
345 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
346 struct nouveau_grobj
*eng3d
= nvfx
->screen
->eng3d
;
347 unsigned num_outputs
= nvfx
->vertprog
->draw_elements
;
348 int elements
= MAX2(num_outputs
, nvfx
->hw_vtxelt_nr
);
353 BEGIN_RING(chan
, eng3d
, NV30_3D_VTXFMT(0), elements
);
354 for(unsigned i
= 0; i
< num_outputs
; ++i
)
355 OUT_RING(chan
, (4 << NV30_3D_VTXFMT_SIZE__SHIFT
) | NV30_3D_VTXFMT_TYPE_V32_FLOAT
);
356 for(unsigned i
= num_outputs
; i
< elements
; ++i
)
357 OUT_RING(chan
, NV30_3D_VTXFMT_TYPE_V32_FLOAT
);
361 /* seems to be some kind of cache flushing */
362 for(i
= 0; i
< 3; ++i
) {
363 BEGIN_RING(chan
, eng3d
, 0x1718, 1);
368 BEGIN_RING(chan
, eng3d
, NV30_3D_VTXBUF(0), elements
);
369 for (unsigned i
= 0; i
< elements
; i
++)
372 BEGIN_RING(chan
, eng3d
, 0x1710, 1);
375 nvfx
->hw_vtxelt_nr
= num_outputs
;
376 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_VTXBUF
;
380 nvfx_vbo_relocate(struct nvfx_context
*nvfx
)
382 struct nouveau_channel
* chan
;
386 if(!nvfx
->use_vertex_buffers
)
389 chan
= nvfx
->screen
->base
.channel
;
390 vb_flags
= nvfx
->screen
->vertex_buffer_reloc_flags
| NOUVEAU_BO_RD
| NOUVEAU_BO_DUMMY
;
392 MARK_RING(chan
, 2 * 16 + 3, 2 * 16 + 3);
393 for (i
= 0; i
< nvfx
->vtxelt
->num_per_vertex
; i
++) {
394 struct nvfx_per_vertex_element
*ve
= &nvfx
->vtxelt
->per_vertex
[i
];
395 struct pipe_vertex_buffer
*vb
= &nvfx
->vtxbuf
[ve
->vertex_buffer_index
];
396 struct nouveau_bo
* bo
= nvfx_resource(vb
->buffer
)->bo
;
398 OUT_RELOC(chan
, bo
, RING_3D(NV30_3D_VTXBUF(ve
->idx
), 1),
400 OUT_RELOC(chan
, bo
, vb
->buffer_offset
+ ve
->src_offset
+ nvfx
->base_vertex
* vb
->stride
,
401 vb_flags
| NOUVEAU_BO_LOW
| NOUVEAU_BO_OR
,
402 0, NV30_3D_VTXBUF_DMA1
);
404 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_VTXBUF
;
408 nvfx_idxbuf_emit(struct nvfx_context
* nvfx
, unsigned ib_flags
)
410 struct nouveau_channel
* chan
= nvfx
->screen
->base
.channel
;
411 unsigned ib_format
= (nvfx
->idxbuf
.index_size
== 2) ? NV30_3D_IDXBUF_FORMAT_TYPE_U16
: NV30_3D_IDXBUF_FORMAT_TYPE_U32
;
412 struct nouveau_bo
* bo
= nvfx_resource(nvfx
->idxbuf
.buffer
)->bo
;
413 ib_flags
|= nvfx
->screen
->index_buffer_reloc_flags
| NOUVEAU_BO_RD
;
415 assert(nvfx
->screen
->index_buffer_reloc_flags
);
417 MARK_RING(chan
, 3, 3);
418 if(ib_flags
& NOUVEAU_BO_DUMMY
)
419 OUT_RELOC(chan
, bo
, RING_3D(NV30_3D_IDXBUF_OFFSET
, 2), ib_flags
, 0, 0);
421 OUT_RING(chan
, RING_3D(NV30_3D_IDXBUF_OFFSET
, 2));
422 OUT_RELOC(chan
, bo
, nvfx
->idxbuf
.offset
+ 1, ib_flags
| NOUVEAU_BO_LOW
, 0, 0);
423 OUT_RELOC(chan
, bo
, ib_format
, ib_flags
| NOUVEAU_BO_OR
,
424 0, NV30_3D_IDXBUF_FORMAT_DMA1
);
425 nvfx
->relocs_needed
&=~ NVFX_RELOCATE_IDXBUF
;
429 nvfx_idxbuf_validate(struct nvfx_context
* nvfx
)
431 nvfx_idxbuf_emit(nvfx
, 0);
435 nvfx_idxbuf_relocate(struct nvfx_context
* nvfx
)
437 nvfx_idxbuf_emit(nvfx
, NOUVEAU_BO_DUMMY
);
440 unsigned nvfx_vertex_formats
[PIPE_FORMAT_COUNT
] =
442 [PIPE_FORMAT_R32_FLOAT
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
,
443 [PIPE_FORMAT_R32G32_FLOAT
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
,
444 [PIPE_FORMAT_R32G32B32_FLOAT
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
,
445 [PIPE_FORMAT_R32G32B32A32_FLOAT
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
,
446 [PIPE_FORMAT_R16_FLOAT
] = NV30_3D_VTXFMT_TYPE_V16_FLOAT
,
447 [PIPE_FORMAT_R16G16_FLOAT
] = NV30_3D_VTXFMT_TYPE_V16_FLOAT
,
448 [PIPE_FORMAT_R16G16B16_FLOAT
] = NV30_3D_VTXFMT_TYPE_V16_FLOAT
,
449 [PIPE_FORMAT_R16G16B16A16_FLOAT
] = NV30_3D_VTXFMT_TYPE_V16_FLOAT
,
450 [PIPE_FORMAT_R8_UNORM
] = NV30_3D_VTXFMT_TYPE_U8_UNORM
,
451 [PIPE_FORMAT_R8G8_UNORM
] = NV30_3D_VTXFMT_TYPE_U8_UNORM
,
452 [PIPE_FORMAT_R8G8B8_UNORM
] = NV30_3D_VTXFMT_TYPE_U8_UNORM
,
453 [PIPE_FORMAT_R8G8B8A8_UNORM
] = NV30_3D_VTXFMT_TYPE_U8_UNORM
,
454 [PIPE_FORMAT_R8G8B8A8_USCALED
] = NV30_3D_VTXFMT_TYPE_U8_USCALED
,
455 [PIPE_FORMAT_R16_SNORM
] = NV30_3D_VTXFMT_TYPE_V16_SNORM
,
456 [PIPE_FORMAT_R16G16_SNORM
] = NV30_3D_VTXFMT_TYPE_V16_SNORM
,
457 [PIPE_FORMAT_R16G16B16_SNORM
] = NV30_3D_VTXFMT_TYPE_V16_SNORM
,
458 [PIPE_FORMAT_R16G16B16A16_SNORM
] = NV30_3D_VTXFMT_TYPE_V16_SNORM
,
459 [PIPE_FORMAT_R16_SSCALED
] = NV30_3D_VTXFMT_TYPE_V16_SSCALED
,
460 [PIPE_FORMAT_R16G16_SSCALED
] = NV30_3D_VTXFMT_TYPE_V16_SSCALED
,
461 [PIPE_FORMAT_R16G16B16_SSCALED
] = NV30_3D_VTXFMT_TYPE_V16_SSCALED
,
462 [PIPE_FORMAT_R16G16B16A16_SSCALED
] = NV30_3D_VTXFMT_TYPE_V16_SSCALED
,
466 nvfx_vtxelts_state_create(struct pipe_context
*pipe
,
467 unsigned num_elements
,
468 const struct pipe_vertex_element
*elements
)
470 struct nvfx_vtxelt_state
*cso
= CALLOC_STRUCT(nvfx_vtxelt_state
);
471 struct translate_key transkey
;
472 unsigned per_vertex_size
[16];
473 unsigned vb_compacted_index
[16];
475 if(num_elements
> 16)
477 _debug_printf("Error: application attempted to use %u vertex elements, but only 16 are supported: ignoring the rest\n", num_elements
);
481 memset(per_vertex_size
, 0, sizeof(per_vertex_size
));
482 memcpy(cso
->pipe
, elements
, num_elements
* sizeof(elements
[0]));
483 cso
->num_elements
= num_elements
;
484 cso
->needs_translate
= FALSE
;
486 transkey
.nr_elements
= 0;
487 transkey
.output_stride
= 0;
489 for(unsigned i
= 0; i
< num_elements
; ++i
)
491 const struct pipe_vertex_element
* ve
= &elements
[i
];
492 if(!ve
->instance_divisor
)
493 per_vertex_size
[ve
->vertex_buffer_index
] += util_format_get_stride(ve
->src_format
, 1);
496 for(unsigned i
= 0; i
< 16; ++i
)
498 if(per_vertex_size
[i
])
500 unsigned idx
= cso
->num_per_vertex_buffer_infos
++;
501 cso
->per_vertex_buffer_info
[idx
].vertex_buffer_index
= i
;
502 cso
->per_vertex_buffer_info
[idx
].per_vertex_size
= per_vertex_size
[i
];
503 vb_compacted_index
[i
] = idx
;
507 for(unsigned i
= 0; i
< num_elements
; ++i
)
509 const struct pipe_vertex_element
* ve
= &elements
[i
];
510 unsigned type
= nvfx_vertex_formats
[ve
->src_format
];
511 unsigned ncomp
= util_format_get_nr_components(ve
->src_format
);
513 //if(ve->frequency != PIPE_ELEMENT_FREQUENCY_PER_VERTEX)
514 if(ve
->instance_divisor
)
516 struct nvfx_low_frequency_element
* lfve
;
517 cso
->vtxfmt
[i
] = NV30_3D_VTXFMT_TYPE_V32_FLOAT
;
519 //if(ve->frequency == PIPE_ELEMENT_FREQUENCY_CONSTANT)
521 lfve
= &cso
->constant
[cso
->num_constant
++];
524 lfve
= &cso
->per_instance
[cso
->num_per_instance
++].base
;
525 ((struct nvfx_per_instance_element
*)lfve
)->instance_divisor
= ve
->instance_divisor
;
529 lfve
->vertex_buffer_index
= ve
->vertex_buffer_index
;
530 lfve
->src_offset
= ve
->src_offset
;
531 lfve
->fetch_rgba_float
= util_format_description(ve
->src_format
)->fetch_rgba_float
;
538 idx
= cso
->num_per_vertex
++;
539 cso
->per_vertex
[idx
].idx
= i
;
540 cso
->per_vertex
[idx
].vertex_buffer_index
= ve
->vertex_buffer_index
;
541 cso
->per_vertex
[idx
].src_offset
= ve
->src_offset
;
543 idx
= transkey
.nr_elements
++;
544 transkey
.element
[idx
].input_format
= ve
->src_format
;
545 transkey
.element
[idx
].input_buffer
= vb_compacted_index
[ve
->vertex_buffer_index
];
546 transkey
.element
[idx
].input_offset
= ve
->src_offset
;
547 transkey
.element
[idx
].instance_divisor
= 0;
548 transkey
.element
[idx
].type
= TRANSLATE_ELEMENT_NORMAL
;
551 transkey
.element
[idx
].output_format
= ve
->src_format
;
552 cso
->vtxfmt
[i
] = (ncomp
<< NV30_3D_VTXFMT_SIZE__SHIFT
) | type
;
556 unsigned float32
[4] = {PIPE_FORMAT_R32_FLOAT
, PIPE_FORMAT_R32G32_FLOAT
, PIPE_FORMAT_R32G32B32_FLOAT
, PIPE_FORMAT_R32G32B32A32_FLOAT
};
557 transkey
.element
[idx
].output_format
= float32
[ncomp
- 1];
558 cso
->needs_translate
= TRUE
;
559 cso
->vtxfmt
[i
] = (ncomp
<< NV30_3D_VTXFMT_SIZE__SHIFT
) | NV30_3D_VTXFMT_TYPE_V32_FLOAT
;
561 transkey
.element
[idx
].output_offset
= transkey
.output_stride
;
562 transkey
.output_stride
+= (util_format_get_stride(transkey
.element
[idx
].output_format
, 1) + 3) & ~3;
566 cso
->translate
= translate_create(&transkey
);
567 cso
->vertex_length
= transkey
.output_stride
>> 2;
568 cso
->max_vertices_per_packet
= 2047 / MAX2(cso
->vertex_length
, 1);
574 nvfx_vtxelts_state_delete(struct pipe_context
*pipe
, void *hwcso
)
580 nvfx_vtxelts_state_bind(struct pipe_context
*pipe
, void *hwcso
)
582 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
584 nvfx
->vtxelt
= hwcso
;
585 nvfx
->use_vertex_buffers
= -1;
586 nvfx
->draw_dirty
|= NVFX_NEW_ARRAYS
;
590 nvfx_set_vertex_buffers(struct pipe_context
*pipe
, unsigned count
,
591 const struct pipe_vertex_buffer
*vb
)
593 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
595 util_copy_vertex_buffers(nvfx
->vtxbuf
,
599 nvfx
->use_vertex_buffers
= -1;
600 nvfx
->draw_dirty
|= NVFX_NEW_ARRAYS
;
604 nvfx_set_index_buffer(struct pipe_context
*pipe
,
605 const struct pipe_index_buffer
*ib
)
607 struct nvfx_context
*nvfx
= nvfx_context(pipe
);
611 pipe_resource_reference(&nvfx
->idxbuf
.buffer
, ib
->buffer
);
612 nvfx
->idxbuf
.index_size
= ib
->index_size
;
613 nvfx
->idxbuf
.offset
= ib
->offset
;
617 pipe_resource_reference(&nvfx
->idxbuf
.buffer
, 0);
618 nvfx
->idxbuf
.index_size
= 0;
619 nvfx
->idxbuf
.offset
= 0;
622 nvfx
->dirty
|= NVFX_NEW_INDEX
;
623 nvfx
->draw_dirty
|= NVFX_NEW_INDEX
;
627 nvfx_init_vbo_functions(struct nvfx_context
*nvfx
)
629 nvfx
->pipe
.set_vertex_buffers
= nvfx_set_vertex_buffers
;
630 nvfx
->pipe
.set_index_buffer
= nvfx_set_index_buffer
;
632 nvfx
->pipe
.create_vertex_elements_state
= nvfx_vtxelts_state_create
;
633 nvfx
->pipe
.delete_vertex_elements_state
= nvfx_vtxelts_state_delete
;
634 nvfx
->pipe
.bind_vertex_elements_state
= nvfx_vtxelts_state_bind
;
636 nvfx
->pipe
.redefine_user_buffer
= u_default_redefine_user_buffer
;