revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mesa / src / gallium / drivers / nvfx / nvfx_vbo.c
blobb72379d653694d6a920ad768dafaa91b528fbd78
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 =
19 * = E - F + 2 =
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
25 switch(mode)
27 case PIPE_PRIM_LINES:
28 return indices >> 1;
29 case PIPE_PRIM_TRIANGLES:
31 // avoid an expensive division by 3 using the multiplicative inverse mod 2^32
32 unsigned q;
33 unsigned inv3 = 2863311531;
34 indices >>= 1;
35 q = indices * inv3;
36 if(unlikely(q >= indices))
38 q += inv3;
39 if(q >= indices)
40 q += inv3;
42 return indices + 2;
43 //return indices / 6 + 2;
45 // guess that indexed quads are created by successive connections, since a closed mesh seems unlikely
46 case PIPE_PRIM_QUADS:
47 return (indices >> 1) + 2;
48 // return (indices >> 2) + 2; // if it is a closed mesh
49 default:
50 return indices;
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;
60 unsigned upload_mode;
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;
65 if (info->indexed)
66 unique_vertices = util_guess_unique_indices_count(info->mode, info->count);
67 else
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
75 * future draw calls.
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
91 * by the way.
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;
120 if (info->indexed)
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;
143 else
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;
154 else
155 upload_mode = 0;
157 #ifdef DEBUG
158 if (unlikely(nvfx->screen->trace_draw))
160 fprintf(stderr, "DRAW");
161 if (info->indexed)
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);
171 if (!upload_mode)
172 fprintf(stderr, " -> inline vertex data");
173 else if (upload_mode == 2 || !info->indexed)
174 fprintf(stderr, " -> buffer range");
175 else
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);
183 if (i)
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");
189 #endif
191 return upload_mode;
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;
211 if (upload_mode > 0)
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));
220 if (upload_mode > 1)
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;
230 else
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);
242 else
243 nvfx_push_vbo(pipe, info);
246 boolean
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;
251 int i;
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;
255 if (!elements)
256 return TRUE;
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);
264 float v[4];
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)
273 unsigned idx = 0;
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];
278 if(idx != ve->idx)
280 assert(idx < ve->idx);
281 OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], ve->idx - idx);
282 idx = ve->idx;
285 OUT_RING(chan, nvfx->vtxelt->vtxfmt[idx] | (vb->stride << NV30_3D_VTXFMT_STRIDE__SHIFT));
286 ++idx;
288 if(idx != nvfx->vtxelt->num_elements)
289 OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], nvfx->vtxelt->num_elements - idx);
291 else
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);
297 if(nvfx->is_nv4x) {
298 unsigned i;
299 /* seems to be some kind of cache flushing */
300 for(i = 0; i < 3; ++i) {
301 BEGIN_RING(chan, eng3d, 0x1718, 1);
302 OUT_RING(chan, 0);
306 BEGIN_RING(chan, eng3d, NV30_3D_VTXBUF(0), elements);
307 if(nvfx->use_vertex_buffers)
309 unsigned idx = 0;
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)
316 OUT_RING(chan, 0);
318 OUT_RELOC(chan, bo,
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);
322 ++idx;
325 for(; idx < elements; ++idx)
326 OUT_RING(chan, 0);
328 else
330 for (i = 0; i < elements; i++)
331 OUT_RING(chan, 0);
334 BEGIN_RING(chan, eng3d, 0x1710, 1);
335 OUT_RING(chan, 0);
337 nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements;
338 nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
339 return TRUE;
342 void
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);
350 if (!elements)
351 return;
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);
359 if(nvfx->is_nv4x) {
360 unsigned i;
361 /* seems to be some kind of cache flushing */
362 for(i = 0; i < 3; ++i) {
363 BEGIN_RING(chan, eng3d, 0x1718, 1);
364 OUT_RING(chan, 0);
368 BEGIN_RING(chan, eng3d, NV30_3D_VTXBUF(0), elements);
369 for (unsigned i = 0; i < elements; i++)
370 OUT_RING(chan, 0);
372 BEGIN_RING(chan, eng3d, 0x1710, 1);
373 OUT_RING(chan, 0);
375 nvfx->hw_vtxelt_nr = num_outputs;
376 nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
379 void
380 nvfx_vbo_relocate(struct nvfx_context *nvfx)
382 struct nouveau_channel* chan;
383 unsigned vb_flags;
384 int i;
386 if(!nvfx->use_vertex_buffers)
387 return;
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),
399 vb_flags, 0, 0);
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;
407 static void
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);
420 else
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;
428 void
429 nvfx_idxbuf_validate(struct nvfx_context* nvfx)
431 nvfx_idxbuf_emit(nvfx, 0);
434 void
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,
465 static void *
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);
478 num_elements = 16;
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)
520 if(0)
521 lfve = &cso->constant[cso->num_constant++];
522 else
524 lfve = &cso->per_instance[cso->num_per_instance++].base;
525 ((struct nvfx_per_instance_element*)lfve)->instance_divisor = ve->instance_divisor;
528 lfve->idx = i;
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;
532 lfve->ncomp = ncomp;
534 else
536 unsigned idx;
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;
549 if(type)
551 transkey.element[idx].output_format = ve->src_format;
552 cso->vtxfmt[i] = (ncomp << NV30_3D_VTXFMT_SIZE__SHIFT) | type;
554 else
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);
570 return (void *)cso;
573 static void
574 nvfx_vtxelts_state_delete(struct pipe_context *pipe, void *hwcso)
576 FREE(hwcso);
579 static void
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;
589 static void
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,
596 &nvfx->vtxbuf_nr,
597 vb, count);
599 nvfx->use_vertex_buffers = -1;
600 nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
603 static void
604 nvfx_set_index_buffer(struct pipe_context *pipe,
605 const struct pipe_index_buffer *ib)
607 struct nvfx_context *nvfx = nvfx_context(pipe);
609 if(ib)
611 pipe_resource_reference(&nvfx->idxbuf.buffer, ib->buffer);
612 nvfx->idxbuf.index_size = ib->index_size;
613 nvfx->idxbuf.offset = ib->offset;
615 else
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;
626 void
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;