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 "translate/translate.h"
7
#include "nvfx_context.h"
8
#include "nvfx_state.h"
9
#include "nvfx_resource.h"
11
#include "nouveau/nouveau_channel.h"
13
#include "nouveau/nouveau_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;
251
int elements = MAX2(nvfx->vtxelt->num_elements, nvfx->hw_vtxelt_nr);
252
unsigned vb_flags = nvfx->screen->vertex_buffer_reloc_flags | NOUVEAU_BO_RD;
257
MARK_RING(chan, (5 + 2) * 16 + 2 + 11, 16 + 2);
258
for(unsigned i = 0; i < nvfx->vtxelt->num_constant; ++i)
260
struct nvfx_low_frequency_element *ve = &nvfx->vtxelt->constant[i];
261
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
262
struct nvfx_buffer* buffer = nvfx_buffer(vb->buffer);
264
ve->fetch_rgba_float(v, buffer->data + vb->buffer_offset + ve->src_offset, 0, 0);
265
nvfx_emit_vtx_attr(chan, ve->idx, v, ve->ncomp);
269
OUT_RING(chan, RING_3D(NV30_3D_VTXFMT(0), elements));
270
if(nvfx->use_vertex_buffers)
273
for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
274
struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
275
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
279
assert(idx < ve->idx);
280
OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], ve->idx - idx);
284
OUT_RING(chan, nvfx->vtxelt->vtxfmt[idx] | (vb->stride << NV30_3D_VTXFMT_STRIDE__SHIFT));
287
if(idx != nvfx->vtxelt->num_elements)
288
OUT_RINGp(chan, &nvfx->vtxelt->vtxfmt[idx], nvfx->vtxelt->num_elements - idx);
291
OUT_RINGp(chan, nvfx->vtxelt->vtxfmt, nvfx->vtxelt->num_elements);
293
for(i = nvfx->vtxelt->num_elements; i < elements; ++i)
294
OUT_RING(chan, NV30_3D_VTXFMT_TYPE_V32_FLOAT);
298
/* seems to be some kind of cache flushing */
299
for(i = 0; i < 3; ++i) {
300
OUT_RING(chan, RING_3D(0x1718, 1));
305
OUT_RING(chan, RING_3D(NV30_3D_VTXBUF(0), elements));
306
if(nvfx->use_vertex_buffers)
309
for (i = 0; i < nvfx->vtxelt->num_per_vertex; i++) {
310
struct nvfx_per_vertex_element *ve = &nvfx->vtxelt->per_vertex[i];
311
struct pipe_vertex_buffer *vb = &nvfx->vtxbuf[ve->vertex_buffer_index];
312
struct nouveau_bo* bo = nvfx_resource(vb->buffer)->bo;
314
for(; idx < ve->idx; ++idx)
318
vb->buffer_offset + ve->src_offset + nvfx->base_vertex * vb->stride,
319
vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
320
0, NV30_3D_VTXBUF_DMA1);
324
for(; idx < elements; ++idx)
329
for (i = 0; i < elements; i++)
333
OUT_RING(chan, RING_3D(0x1710, 1));
336
nvfx->hw_vtxelt_nr = nvfx->vtxelt->num_elements;
337
nvfx->relocs_needed &=~ NVFX_RELOCATE_VTXBUF;
342
nvfx_vbo_swtnl_validate(struct nvfx_context *nvfx)
344
struct nouveau_channel* chan = nvfx->screen->base.channel;
345
unsigned num_outputs = nvfx->vertprog->draw_elements;
346
int elements = MAX2(num_outputs, nvfx->hw_vtxelt_nr);
351
WAIT_RING(chan, (1 + 6 + 1 + 2) + elements * 2);
353
OUT_RING(chan, RING_3D(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
OUT_RING(chan, RING_3D(0x1718, 1));
368
OUT_RING(chan, RING_3D(NV30_3D_VTXBUF(0), elements));
369
for (unsigned i = 0; i < elements; i++)
372
OUT_RING(chan, RING_3D(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
for(unsigned i = 0; i < count; ++i)
597
pipe_resource_reference(&nvfx->vtxbuf[i].buffer, vb[i].buffer);
598
nvfx->vtxbuf[i].buffer_offset = vb[i].buffer_offset;
599
nvfx->vtxbuf[i].max_index = vb[i].max_index;
600
nvfx->vtxbuf[i].stride = vb[i].stride;
603
for(unsigned i = count; i < nvfx->vtxbuf_nr; ++i)
604
pipe_resource_reference(&nvfx->vtxbuf[i].buffer, 0);
606
nvfx->vtxbuf_nr = count;
607
nvfx->use_vertex_buffers = -1;
608
nvfx->draw_dirty |= NVFX_NEW_ARRAYS;
612
nvfx_set_index_buffer(struct pipe_context *pipe,
613
const struct pipe_index_buffer *ib)
615
struct nvfx_context *nvfx = nvfx_context(pipe);
619
pipe_resource_reference(&nvfx->idxbuf.buffer, ib->buffer);
620
nvfx->idxbuf.index_size = ib->index_size;
621
nvfx->idxbuf.offset = ib->offset;
625
pipe_resource_reference(&nvfx->idxbuf.buffer, 0);
626
nvfx->idxbuf.index_size = 0;
627
nvfx->idxbuf.offset = 0;
630
nvfx->dirty |= NVFX_NEW_INDEX;
631
nvfx->draw_dirty |= NVFX_NEW_INDEX;
635
nvfx_init_vbo_functions(struct nvfx_context *nvfx)
637
nvfx->pipe.set_vertex_buffers = nvfx_set_vertex_buffers;
638
nvfx->pipe.set_index_buffer = nvfx_set_index_buffer;
640
nvfx->pipe.create_vertex_elements_state = nvfx_vtxelts_state_create;
641
nvfx->pipe.delete_vertex_elements_state = nvfx_vtxelts_state_delete;
642
nvfx->pipe.bind_vertex_elements_state = nvfx_vtxelts_state_bind;