1 /* 2 * Copyright 2010 Christoph Bumiller 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 */ 22 23 #define NVC0_PUSH_EXPLICIT_SPACE_CHECKING 24 25 #include "pipe/p_context.h" 26 #include "pipe/p_state.h" 27 #include "util/u_inlines.h" 28 #include "util/u_format.h" 29 #include "translate/translate.h" 30 31 #include "nvc0/nvc0_context.h" 32 #include "nvc0/nvc0_query_hw.h" 33 #include "nvc0/nvc0_resource.h" 34 35 #include "nvc0/nvc0_3d.xml.h" 36 37 void 38 nvc0_vertex_state_delete(struct pipe_context *pipe, 39 void *hwcso) 40 { 41 struct nvc0_vertex_stateobj *so = hwcso; 42 43 if (so->translate) 44 so->translate->release(so->translate); 45 FREE(hwcso); 46 } 47 48 void * 49 nvc0_vertex_state_create(struct pipe_context *pipe, 50 unsigned num_elements, 51 const struct pipe_vertex_element *elements) 52 { 53 struct nvc0_vertex_stateobj *so; 54 struct translate_key transkey; 55 unsigned i; 56 unsigned src_offset_max = 0; 57 58 so = MALLOC(sizeof(*so) + 59 num_elements * sizeof(struct nvc0_vertex_element)); 60 if (!so) 61 return NULL; 62 so->num_elements = num_elements; 63 so->instance_elts = 0; 64 so->instance_bufs = 0; 65 so->shared_slots = false; 66 so->need_conversion = false; 67 68 memset(so->vb_access_size, 0, sizeof(so->vb_access_size)); 69 70 for (i = 0; i < PIPE_MAX_ATTRIBS; ++i) 71 so->min_instance_div[i] = 0xffffffff; 72 73 transkey.nr_elements = 0; 74 transkey.output_stride = 0; 75 76 for (i = 0; i < num_elements; ++i) { 77 const struct pipe_vertex_element *ve = &elements[i]; 78 const unsigned vbi = ve->vertex_buffer_index; 79 unsigned size; 80 enum pipe_format fmt = ve->src_format; 81 82 so->element[i].pipe = elements[i]; 83 so->element[i].state = nvc0_vertex_format[fmt].vtx; 84 85 if (!so->element[i].state) { 86 switch (util_format_get_nr_components(fmt)) { 87 case 1: fmt = PIPE_FORMAT_R32_FLOAT; break; 88 case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break; 89 case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break; 90 case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break; 91 default: 92 assert(0); 93 FREE(so); 94 return NULL; 95 } 96 so->element[i].state = nvc0_vertex_format[fmt].vtx; 97 so->need_conversion = true; 98 pipe_debug_message(&nouveau_context(pipe)->debug, FALLBACK, 99 "Converting vertex element %d, no hw format %s", 100 i, util_format_name(ve->src_format)); 101 } 102 size = util_format_get_blocksize(fmt); 103 104 src_offset_max = MAX2(src_offset_max, ve->src_offset); 105 106 if (so->vb_access_size[vbi] < (ve->src_offset + size)) 107 so->vb_access_size[vbi] = ve->src_offset + size; 108 109 if (unlikely(ve->instance_divisor)) { 110 so->instance_elts |= 1 << i; 111 so->instance_bufs |= 1 << vbi; 112 if (ve->instance_divisor < so->min_instance_div[vbi]) 113 so->min_instance_div[vbi] = ve->instance_divisor; 114 } 115 116 if (1) { 117 unsigned ca; 118 unsigned j = transkey.nr_elements++; 119 120 ca = util_format_description(fmt)->channel[0].size / 8; 121 if (ca != 1 && ca != 2) 122 ca = 4; 123 124 transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL; 125 transkey.element[j].input_format = ve->src_format; 126 transkey.element[j].input_buffer = vbi; 127 transkey.element[j].input_offset = ve->src_offset; 128 transkey.element[j].instance_divisor = ve->instance_divisor; 129 130 transkey.output_stride = align(transkey.output_stride, ca); 131 transkey.element[j].output_format = fmt; 132 transkey.element[j].output_offset = transkey.output_stride; 133 transkey.output_stride += size; 134 135 so->element[i].state_alt = so->element[i].state; 136 so->element[i].state_alt |= transkey.element[j].output_offset << 7; 137 } 138 139 so->element[i].state |= i << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT; 140 } 141 transkey.output_stride = align(transkey.output_stride, 4); 142 143 so->size = transkey.output_stride; 144 so->translate = translate_create(&transkey); 145 146 if (so->instance_elts || src_offset_max >= (1 << 14)) 147 return so; 148 so->shared_slots = true; 149 150 for (i = 0; i < num_elements; ++i) { 151 const unsigned b = elements[i].vertex_buffer_index; 152 const unsigned s = elements[i].src_offset; 153 so->element[i].state &= ~NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__MASK; 154 so->element[i].state |= b << NVC0_3D_VERTEX_ATTRIB_FORMAT_BUFFER__SHIFT; 155 so->element[i].state |= s << NVC0_3D_VERTEX_ATTRIB_FORMAT_OFFSET__SHIFT; 156 } 157 return so; 158 } 159 160 #define NVC0_3D_VERTEX_ATTRIB_INACTIVE \ 161 NVC0_3D_VERTEX_ATTRIB_FORMAT_TYPE_FLOAT | \ 162 NVC0_3D_VERTEX_ATTRIB_FORMAT_SIZE_32 | NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST 163 164 #define VTX_ATTR(a, c, t, s) \ 165 ((NVC0_3D_VTX_ATTR_DEFINE_TYPE_##t) | \ 166 (NVC0_3D_VTX_ATTR_DEFINE_SIZE_##s) | \ 167 ((a) << NVC0_3D_VTX_ATTR_DEFINE_ATTR__SHIFT) | \ 168 ((c) << NVC0_3D_VTX_ATTR_DEFINE_COMP__SHIFT)) 169 170 static void 171 nvc0_set_constant_vertex_attrib(struct nvc0_context *nvc0, const unsigned a) 172 { 173 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 174 struct pipe_vertex_element *ve = &nvc0->vertex->element[a].pipe; 175 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[ve->vertex_buffer_index]; 176 uint32_t mode; 177 const struct util_format_description *desc; 178 void *dst; 179 const void *src = (const uint8_t *)vb->user_buffer + ve->src_offset; 180 assert(!vb->buffer); 181 182 desc = util_format_description(ve->src_format); 183 184 PUSH_SPACE(push, 6); 185 BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 5); 186 dst = &push->cur[1]; 187 if (desc->channel[0].pure_integer) { 188 if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED) { 189 mode = VTX_ATTR(a, 4, SINT, 32); 190 desc->unpack_rgba_sint(dst, 0, src, 0, 1, 1); 191 } else { 192 mode = VTX_ATTR(a, 4, UINT, 32); 193 desc->unpack_rgba_uint(dst, 0, src, 0, 1, 1); 194 } 195 } else { 196 mode = VTX_ATTR(a, 4, FLOAT, 32); 197 desc->unpack_rgba_float(dst, 0, src, 0, 1, 1); 198 } 199 push->cur[0] = mode; 200 push->cur += 5; 201 } 202 203 static inline void 204 nvc0_user_vbuf_range(struct nvc0_context *nvc0, int vbi, 205 uint32_t *base, uint32_t *size) 206 { 207 if (unlikely(nvc0->vertex->instance_bufs & (1 << vbi))) { 208 const uint32_t div = nvc0->vertex->min_instance_div[vbi]; 209 *base = nvc0->instance_off * nvc0->vtxbuf[vbi].stride; 210 *size = (nvc0->instance_max / div) * nvc0->vtxbuf[vbi].stride + 211 nvc0->vertex->vb_access_size[vbi]; 212 } else { 213 /* NOTE: if there are user buffers, we *must* have index bounds */ 214 assert(nvc0->vb_elt_limit != ~0); 215 *base = nvc0->vb_elt_first * nvc0->vtxbuf[vbi].stride; 216 *size = nvc0->vb_elt_limit * nvc0->vtxbuf[vbi].stride + 217 nvc0->vertex->vb_access_size[vbi]; 218 } 219 } 220 221 static inline void 222 nvc0_release_user_vbufs(struct nvc0_context *nvc0) 223 { 224 if (nvc0->vbo_user) { 225 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX_TMP); 226 nouveau_scratch_done(&nvc0->base); 227 } 228 } 229 230 static void 231 nvc0_update_user_vbufs(struct nvc0_context *nvc0) 232 { 233 uint64_t address[PIPE_MAX_ATTRIBS]; 234 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 235 int i; 236 uint32_t written = 0; 237 238 PUSH_SPACE(push, nvc0->vertex->num_elements * 8); 239 for (i = 0; i < nvc0->vertex->num_elements; ++i) { 240 struct pipe_vertex_element *ve = &nvc0->vertex->element[i].pipe; 241 const unsigned b = ve->vertex_buffer_index; 242 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b]; 243 uint32_t base, size; 244 245 if (!(nvc0->vbo_user & (1 << b))) 246 continue; 247 if (nvc0->constant_vbos & (1 << b)) { 248 nvc0_set_constant_vertex_attrib(nvc0, i); 249 continue; 250 } 251 nvc0_user_vbuf_range(nvc0, b, &base, &size); 252 253 if (!(written & (1 << b))) { 254 struct nouveau_bo *bo; 255 const uint32_t bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART; 256 written |= 1 << b; 257 address[b] = nouveau_scratch_data(&nvc0->base, vb->user_buffer, 258 base, size, &bo); 259 if (bo) 260 BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, bo_flags, bo); 261 262 NOUVEAU_DRV_STAT(&nvc0->screen->base, user_buffer_upload_bytes, size); 263 } 264 265 BEGIN_1IC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_SELECT), 5); 266 PUSH_DATA (push, i); 267 PUSH_DATAh(push, address[b] + base + size - 1); 268 PUSH_DATA (push, address[b] + base + size - 1); 269 PUSH_DATAh(push, address[b] + ve->src_offset); 270 PUSH_DATA (push, address[b] + ve->src_offset); 271 } 272 nvc0->base.vbo_dirty = true; 273 } 274 275 static void 276 nvc0_update_user_vbufs_shared(struct nvc0_context *nvc0) 277 { 278 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 279 uint32_t mask = nvc0->vbo_user & ~nvc0->constant_vbos; 280 281 PUSH_SPACE(push, nvc0->num_vtxbufs * 8); 282 while (mask) { 283 struct nouveau_bo *bo; 284 const uint32_t bo_flags = NOUVEAU_BO_RD | NOUVEAU_BO_GART; 285 uint64_t address; 286 uint32_t base, size; 287 const int b = ffs(mask) - 1; 288 mask &= ~(1 << b); 289 290 nvc0_user_vbuf_range(nvc0, b, &base, &size); 291 292 address = nouveau_scratch_data(&nvc0->base, nvc0->vtxbuf[b].user_buffer, 293 base, size, &bo); 294 if (bo) 295 BCTX_REFN_bo(nvc0->bufctx_3d, 3D_VTX_TMP, bo_flags, bo); 296 297 BEGIN_1IC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_SELECT), 5); 298 PUSH_DATA (push, b); 299 PUSH_DATAh(push, address + base + size - 1); 300 PUSH_DATA (push, address + base + size - 1); 301 PUSH_DATAh(push, address); 302 PUSH_DATA (push, address); 303 304 NOUVEAU_DRV_STAT(&nvc0->screen->base, user_buffer_upload_bytes, size); 305 } 306 307 mask = nvc0->state.constant_elts; 308 while (mask) { 309 int i = ffs(mask) - 1; 310 mask &= ~(1 << i); 311 nvc0_set_constant_vertex_attrib(nvc0, i); 312 } 313 } 314 315 static void 316 nvc0_validate_vertex_buffers(struct nvc0_context *nvc0) 317 { 318 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 319 const struct nvc0_vertex_stateobj *vertex = nvc0->vertex; 320 uint32_t refd = 0; 321 unsigned i; 322 323 PUSH_SPACE(push, vertex->num_elements * 8); 324 for (i = 0; i < vertex->num_elements; ++i) { 325 const struct nvc0_vertex_element *ve; 326 const struct pipe_vertex_buffer *vb; 327 struct nv04_resource *res; 328 unsigned b; 329 unsigned limit, offset; 330 331 if (nvc0->state.constant_elts & (1 << i)) 332 continue; 333 ve = &vertex->element[i]; 334 b = ve->pipe.vertex_buffer_index; 335 vb = &nvc0->vtxbuf[b]; 336 337 if (nvc0->vbo_user & (1 << b)) { 338 if (!(nvc0->constant_vbos & (1 << b))) { 339 if (ve->pipe.instance_divisor) { 340 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_DIVISOR(i)), 1); 341 PUSH_DATA (push, ve->pipe.instance_divisor); 342 } 343 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 1); 344 PUSH_DATA (push, (1 << 12) | vb->stride); 345 } 346 /* address/value set in nvc0_update_user_vbufs */ 347 continue; 348 } 349 res = nv04_resource(vb->buffer); 350 offset = ve->pipe.src_offset + vb->buffer_offset; 351 limit = vb->buffer->width0 - 1; 352 353 if (unlikely(ve->pipe.instance_divisor)) { 354 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 4); 355 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 356 PUSH_DATAh(push, res->address + offset); 357 PUSH_DATA (push, res->address + offset); 358 PUSH_DATA (push, ve->pipe.instance_divisor); 359 } else { 360 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 3); 361 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 362 PUSH_DATAh(push, res->address + offset); 363 PUSH_DATA (push, res->address + offset); 364 } 365 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(i)), 2); 366 PUSH_DATAh(push, res->address + limit); 367 PUSH_DATA (push, res->address + limit); 368 369 if (!(refd & (1 << b))) { 370 refd |= 1 << b; 371 BCTX_REFN(nvc0->bufctx_3d, 3D_VTX, res, RD); 372 } 373 } 374 if (nvc0->vbo_user) 375 nvc0_update_user_vbufs(nvc0); 376 } 377 378 static void 379 nvc0_validate_vertex_buffers_shared(struct nvc0_context *nvc0) 380 { 381 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 382 unsigned b; 383 const uint32_t mask = nvc0->vbo_user; 384 385 PUSH_SPACE(push, nvc0->num_vtxbufs * 8 + nvc0->vertex->num_elements); 386 for (b = 0; b < nvc0->num_vtxbufs; ++b) { 387 struct pipe_vertex_buffer *vb = &nvc0->vtxbuf[b]; 388 struct nv04_resource *buf; 389 uint32_t offset, limit; 390 391 if (mask & (1 << b)) { 392 if (!(nvc0->constant_vbos & (1 << b))) { 393 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 1); 394 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 395 } 396 /* address/value set in nvc0_update_user_vbufs_shared */ 397 continue; 398 } else if (!vb->buffer) { 399 /* there can be holes in the vertex buffer lists */ 400 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 0); 401 continue; 402 } 403 buf = nv04_resource(vb->buffer); 404 offset = vb->buffer_offset; 405 limit = buf->base.width0 - 1; 406 407 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 3); 408 PUSH_DATA (push, NVC0_3D_VERTEX_ARRAY_FETCH_ENABLE | vb->stride); 409 PUSH_DATAh(push, buf->address + offset); 410 PUSH_DATA (push, buf->address + offset); 411 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_LIMIT_HIGH(b)), 2); 412 PUSH_DATAh(push, buf->address + limit); 413 PUSH_DATA (push, buf->address + limit); 414 415 BCTX_REFN(nvc0->bufctx_3d, 3D_VTX, buf, RD); 416 } 417 /* If there are more elements than buffers, we might not have unset 418 * fetching on the later elements. 419 */ 420 for (; b < nvc0->vertex->num_elements; ++b) 421 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(b)), 0); 422 423 if (nvc0->vbo_user) 424 nvc0_update_user_vbufs_shared(nvc0); 425 } 426 427 void 428 nvc0_vertex_arrays_validate(struct nvc0_context *nvc0) 429 { 430 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 431 struct nvc0_vertex_stateobj *vertex = nvc0->vertex; 432 struct nvc0_vertex_element *ve; 433 uint32_t const_vbos; 434 unsigned i; 435 uint8_t vbo_mode; 436 bool update_vertex; 437 438 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_VTX); 439 440 assert(vertex); 441 if (unlikely(vertex->need_conversion) || 442 unlikely(nvc0->vertprog->vp.edgeflag < PIPE_MAX_ATTRIBS)) { 443 vbo_mode = 3; 444 } else if (nvc0->vbo_user & ~nvc0->constant_vbos) { 445 vbo_mode = nvc0->vbo_push_hint ? 1 : 0; 446 } else { 447 vbo_mode = 0; 448 } 449 const_vbos = vbo_mode ? 0 : nvc0->constant_vbos; 450 451 update_vertex = (nvc0->dirty_3d & NVC0_NEW_3D_VERTEX) || 452 (const_vbos != nvc0->state.constant_vbos) || 453 (vbo_mode != nvc0->state.vbo_mode); 454 455 if (update_vertex) { 456 const unsigned n = MAX2(vertex->num_elements, nvc0->state.num_vtxelts); 457 458 nvc0->state.constant_vbos = const_vbos; 459 nvc0->state.constant_elts = 0; 460 nvc0->state.num_vtxelts = vertex->num_elements; 461 nvc0->state.vbo_mode = vbo_mode; 462 463 if (unlikely(vbo_mode)) { 464 if (unlikely(nvc0->state.instance_elts & 3)) { 465 /* translate mode uses only 2 vertex buffers */ 466 nvc0->state.instance_elts &= ~3; 467 PUSH_SPACE(push, 3); 468 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_PER_INSTANCE(0)), 2); 469 PUSH_DATA (push, 0); 470 PUSH_DATA (push, 0); 471 } 472 473 PUSH_SPACE(push, n * 2 + 4); 474 475 BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 476 for (i = 0; i < vertex->num_elements; ++i) 477 PUSH_DATA(push, vertex->element[i].state_alt); 478 for (; i < n; ++i) 479 PUSH_DATA(push, NVC0_3D_VERTEX_ATTRIB_INACTIVE); 480 481 BEGIN_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(0)), 1); 482 PUSH_DATA (push, (1 << 12) | vertex->size); 483 for (i = 1; i < n; ++i) 484 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 485 } else { 486 uint32_t *restrict data; 487 488 if (unlikely(vertex->instance_elts != nvc0->state.instance_elts)) { 489 nvc0->state.instance_elts = vertex->instance_elts; 490 assert(n); /* if (n == 0), both masks should be 0 */ 491 PUSH_SPACE(push, 3); 492 BEGIN_NVC0(push, NVC0_3D(MACRO_VERTEX_ARRAY_PER_INSTANCE), 2); 493 PUSH_DATA (push, n); 494 PUSH_DATA (push, vertex->instance_elts); 495 } 496 497 PUSH_SPACE(push, n * 2 + 1); 498 BEGIN_NVC0(push, NVC0_3D(VERTEX_ATTRIB_FORMAT(0)), n); 499 data = push->cur; 500 push->cur += n; 501 for (i = 0; i < vertex->num_elements; ++i) { 502 ve = &vertex->element[i]; 503 data[i] = ve->state; 504 if (unlikely(const_vbos & (1 << ve->pipe.vertex_buffer_index))) { 505 nvc0->state.constant_elts |= 1 << i; 506 data[i] |= NVC0_3D_VERTEX_ATTRIB_FORMAT_CONST; 507 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 508 } 509 } 510 for (; i < n; ++i) { 511 data[i] = NVC0_3D_VERTEX_ATTRIB_INACTIVE; 512 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FETCH(i)), 0); 513 } 514 } 515 } 516 if (nvc0->state.vbo_mode) /* using translate, don't set up arrays here */ 517 return; 518 519 if (vertex->shared_slots) 520 nvc0_validate_vertex_buffers_shared(nvc0); 521 else 522 nvc0_validate_vertex_buffers(nvc0); 523 } 524 525 void 526 nvc0_idxbuf_validate(struct nvc0_context *nvc0) 527 { 528 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 529 struct nv04_resource *buf = nv04_resource(nvc0->idxbuf.buffer); 530 531 assert(buf); 532 assert(nouveau_resource_mapped_by_gpu(&buf->base)); 533 534 PUSH_SPACE(push, 6); 535 BEGIN_NVC0(push, NVC0_3D(INDEX_ARRAY_START_HIGH), 5); 536 PUSH_DATAh(push, buf->address + nvc0->idxbuf.offset); 537 PUSH_DATA (push, buf->address + nvc0->idxbuf.offset); 538 PUSH_DATAh(push, buf->address + buf->base.width0 - 1); 539 PUSH_DATA (push, buf->address + buf->base.width0 - 1); 540 PUSH_DATA (push, nvc0->idxbuf.index_size >> 1); 541 542 BCTX_REFN(nvc0->bufctx_3d, 3D_IDX, buf, RD); 543 } 544 545 #define NVC0_PRIM_GL_CASE(n) \ 546 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n 547 548 static inline unsigned 549 nvc0_prim_gl(unsigned prim) 550 { 551 switch (prim) { 552 NVC0_PRIM_GL_CASE(POINTS); 553 NVC0_PRIM_GL_CASE(LINES); 554 NVC0_PRIM_GL_CASE(LINE_LOOP); 555 NVC0_PRIM_GL_CASE(LINE_STRIP); 556 NVC0_PRIM_GL_CASE(TRIANGLES); 557 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP); 558 NVC0_PRIM_GL_CASE(TRIANGLE_FAN); 559 NVC0_PRIM_GL_CASE(QUADS); 560 NVC0_PRIM_GL_CASE(QUAD_STRIP); 561 NVC0_PRIM_GL_CASE(POLYGON); 562 NVC0_PRIM_GL_CASE(LINES_ADJACENCY); 563 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY); 564 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY); 565 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY); 566 NVC0_PRIM_GL_CASE(PATCHES); 567 default: 568 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS; 569 } 570 } 571 572 static void 573 nvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push) 574 { 575 struct nvc0_screen *screen = push->user_priv; 576 577 nouveau_fence_update(&screen->base, true); 578 579 NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); 580 } 581 582 static void 583 nvc0_draw_arrays(struct nvc0_context *nvc0, 584 unsigned mode, unsigned start, unsigned count, 585 unsigned instance_count) 586 { 587 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 588 unsigned prim; 589 590 if (nvc0->state.index_bias) { 591 /* index_bias is implied 0 if !info->indexed (really ?) */ 592 /* TODO: can we deactivate it for the VERTEX_BUFFER_FIRST command ? */ 593 PUSH_SPACE(push, 2); 594 IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 595 IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 596 nvc0->state.index_bias = 0; 597 } 598 599 prim = nvc0_prim_gl(mode); 600 601 while (instance_count--) { 602 PUSH_SPACE(push, 6); 603 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 604 PUSH_DATA (push, prim); 605 BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 606 PUSH_DATA (push, start); 607 PUSH_DATA (push, count); 608 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 609 610 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 611 } 612 NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_array, 1); 613 } 614 615 static void 616 nvc0_draw_elements_inline_u08(struct nouveau_pushbuf *push, const uint8_t *map, 617 unsigned start, unsigned count) 618 { 619 map += start; 620 621 if (count & 3) { 622 unsigned i; 623 PUSH_SPACE(push, 4); 624 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), count & 3); 625 for (i = 0; i < (count & 3); ++i) 626 PUSH_DATA(push, *map++); 627 count &= ~3; 628 } 629 while (count) { 630 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 4) / 4; 631 632 PUSH_SPACE(push, nr + 1); 633 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U8), nr); 634 for (i = 0; i < nr; ++i) { 635 PUSH_DATA(push, 636 (map[3] << 24) | (map[2] << 16) | (map[1] << 8) | map[0]); 637 map += 4; 638 } 639 count -= nr * 4; 640 } 641 } 642 643 static void 644 nvc0_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map, 645 unsigned start, unsigned count) 646 { 647 map += start; 648 649 if (count & 1) { 650 count &= ~1; 651 PUSH_SPACE(push, 2); 652 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 653 PUSH_DATA (push, *map++); 654 } 655 while (count) { 656 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 657 658 PUSH_SPACE(push, nr + 1); 659 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 660 for (i = 0; i < nr; ++i) { 661 PUSH_DATA(push, (map[1] << 16) | map[0]); 662 map += 2; 663 } 664 count -= nr * 2; 665 } 666 } 667 668 static void 669 nvc0_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map, 670 unsigned start, unsigned count) 671 { 672 map += start; 673 674 while (count) { 675 const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); 676 677 PUSH_SPACE(push, nr + 1); 678 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), nr); 679 PUSH_DATAp(push, map, nr); 680 681 map += nr; 682 count -= nr; 683 } 684 } 685 686 static void 687 nvc0_draw_elements_inline_u32_short(struct nouveau_pushbuf *push, 688 const uint32_t *map, 689 unsigned start, unsigned count) 690 { 691 map += start; 692 693 if (count & 1) { 694 count--; 695 PUSH_SPACE(push, 2); 696 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 697 PUSH_DATA (push, *map++); 698 } 699 while (count) { 700 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 701 702 PUSH_SPACE(push, nr + 1); 703 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 704 for (i = 0; i < nr; ++i) { 705 PUSH_DATA(push, (map[1] << 16) | map[0]); 706 map += 2; 707 } 708 count -= nr * 2; 709 } 710 } 711 712 static void 713 nvc0_draw_elements(struct nvc0_context *nvc0, bool shorten, 714 unsigned mode, unsigned start, unsigned count, 715 unsigned instance_count, int32_t index_bias) 716 { 717 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 718 unsigned prim; 719 const unsigned index_size = nvc0->idxbuf.index_size; 720 721 prim = nvc0_prim_gl(mode); 722 723 if (index_bias != nvc0->state.index_bias) { 724 PUSH_SPACE(push, 4); 725 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 1); 726 PUSH_DATA (push, index_bias); 727 BEGIN_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 1); 728 PUSH_DATA (push, index_bias); 729 nvc0->state.index_bias = index_bias; 730 } 731 732 if (nvc0->idxbuf.buffer) { 733 PUSH_SPACE(push, 1); 734 IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), prim); 735 do { 736 PUSH_SPACE(push, 7); 737 BEGIN_NVC0(push, NVC0_3D(INDEX_BATCH_FIRST), 2); 738 PUSH_DATA (push, start); 739 PUSH_DATA (push, count); 740 if (--instance_count) { 741 BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 2); 742 PUSH_DATA (push, 0); 743 PUSH_DATA (push, prim | NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT); 744 } 745 } while (instance_count); 746 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 747 } else { 748 const void *data = nvc0->idxbuf.user_buffer; 749 750 while (instance_count--) { 751 PUSH_SPACE(push, 2); 752 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 753 PUSH_DATA (push, prim); 754 switch (index_size) { 755 case 1: 756 nvc0_draw_elements_inline_u08(push, data, start, count); 757 break; 758 case 2: 759 nvc0_draw_elements_inline_u16(push, data, start, count); 760 break; 761 case 4: 762 if (shorten) 763 nvc0_draw_elements_inline_u32_short(push, data, start, count); 764 else 765 nvc0_draw_elements_inline_u32(push, data, start, count); 766 break; 767 default: 768 assert(0); 769 return; 770 } 771 PUSH_SPACE(push, 1); 772 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 773 774 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 775 } 776 } 777 NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_indexed, 1); 778 } 779 780 static void 781 nvc0_draw_stream_output(struct nvc0_context *nvc0, 782 const struct pipe_draw_info *info) 783 { 784 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 785 struct nvc0_so_target *so = nvc0_so_target(info->count_from_stream_output); 786 struct nv04_resource *res = nv04_resource(so->pipe.buffer); 787 unsigned mode = nvc0_prim_gl(info->mode); 788 unsigned num_instances = info->instance_count; 789 790 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 791 res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 792 PUSH_SPACE(push, 2); 793 IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 794 nvc0_hw_query_fifo_wait(nvc0, nvc0_query(so->pq)); 795 if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 796 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 797 798 NOUVEAU_DRV_STAT(&nvc0->screen->base, gpu_serialize_count, 1); 799 } 800 801 while (num_instances--) { 802 nouveau_pushbuf_space(push, 16, 0, 1); 803 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 804 PUSH_DATA (push, mode); 805 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BASE), 1); 806 PUSH_DATA (push, 0); 807 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_STRIDE), 1); 808 PUSH_DATA (push, so->stride); 809 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BYTES), 1); 810 nvc0_hw_query_pushbuf_submit(push, nvc0_query(so->pq), 0x4); 811 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 812 813 mode |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 814 } 815 } 816 817 static void 818 nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info) 819 { 820 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 821 struct nv04_resource *buf = nv04_resource(info->indirect); 822 struct nv04_resource *buf_count = nv04_resource(info->indirect_params); 823 unsigned size, macro, count = info->indirect_count, drawid = info->drawid; 824 uint32_t offset = buf->offset + info->indirect_offset; 825 struct nvc0_screen *screen = nvc0->screen; 826 827 PUSH_SPACE(push, 7); 828 829 /* must make FIFO wait for engines idle before continuing to process */ 830 if ((buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)) || 831 (buf_count && buf_count->fence_wr && 832 !nouveau_fence_signalled(buf_count->fence_wr))) { 833 IMMED_NVC0(push, SUBC_3D(NV10_SUBCHAN_REF_CNT), 0); 834 } 835 836 /* Queue things up to let the macros write params to the driver constbuf */ 837 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 838 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 839 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 840 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 841 BEGIN_NVC0(push, NVC0_3D(CB_POS), 1); 842 PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO); 843 844 if (info->indexed) { 845 assert(nvc0->idxbuf.buffer); 846 assert(nouveau_resource_mapped_by_gpu(nvc0->idxbuf.buffer)); 847 size = 5; 848 if (buf_count) 849 macro = NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT_COUNT; 850 else 851 macro = NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT; 852 } else { 853 if (nvc0->state.index_bias) { 854 /* index_bias is implied 0 if !info->indexed (really ?) */ 855 IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 856 IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 857 nvc0->state.index_bias = 0; 858 } 859 size = 4; 860 if (buf_count) 861 macro = NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT_COUNT; 862 else 863 macro = NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT; 864 } 865 866 /* If the stride is not the natural stride, we have to stick a separate 867 * push data reference for each draw. Otherwise it can all go in as one. 868 * Of course there is a maximum packet size, so we have to break things up 869 * along those borders as well. 870 */ 871 while (count) { 872 unsigned draws = count, pushes, i; 873 if (info->indirect_stride == size * 4) { 874 draws = MIN2(draws, (NV04_PFIFO_MAX_PACKET_LEN - 4) / size); 875 pushes = 1; 876 } else { 877 draws = MIN2(draws, 32); 878 pushes = draws; 879 } 880 881 nouveau_pushbuf_space(push, 16, 0, pushes + !!buf_count); 882 PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); 883 if (buf_count) 884 PUSH_REFN(push, buf_count->bo, NOUVEAU_BO_RD | buf_count->domain); 885 PUSH_DATA(push, 886 NVC0_FIFO_PKHDR_1I(0, macro, 3 + !!buf_count + draws * size)); 887 PUSH_DATA(push, nvc0_prim_gl(info->mode)); 888 PUSH_DATA(push, drawid); 889 PUSH_DATA(push, draws); 890 if (buf_count) { 891 nouveau_pushbuf_data(push, 892 buf_count->bo, 893 buf_count->offset + info->indirect_params_offset, 894 NVC0_IB_ENTRY_1_NO_PREFETCH | 4); 895 } 896 if (pushes == 1) { 897 nouveau_pushbuf_data(push, 898 buf->bo, offset, 899 NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4 * draws)); 900 offset += draws * info->indirect_stride; 901 } else { 902 for (i = 0; i < pushes; i++) { 903 nouveau_pushbuf_data(push, 904 buf->bo, offset, 905 NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4)); 906 offset += info->indirect_stride; 907 } 908 } 909 count -= draws; 910 drawid += draws; 911 } 912 } 913 914 static inline void 915 nvc0_update_prim_restart(struct nvc0_context *nvc0, bool en, uint32_t index) 916 { 917 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 918 919 if (en != nvc0->state.prim_restart) { 920 if (en) { 921 BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 2); 922 PUSH_DATA (push, 1); 923 PUSH_DATA (push, index); 924 } else { 925 IMMED_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 0); 926 } 927 nvc0->state.prim_restart = en; 928 } else 929 if (en) { 930 BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_INDEX), 1); 931 PUSH_DATA (push, index); 932 } 933 } 934 935 void 936 nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) 937 { 938 struct nvc0_context *nvc0 = nvc0_context(pipe); 939 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 940 struct nvc0_screen *screen = nvc0->screen; 941 int s; 942 943 /* NOTE: caller must ensure that (min_index + index_bias) is >= 0 */ 944 nvc0->vb_elt_first = info->min_index + info->index_bias; 945 nvc0->vb_elt_limit = info->max_index - info->min_index; 946 nvc0->instance_off = info->start_instance; 947 nvc0->instance_max = info->instance_count - 1; 948 949 /* For picking only a few vertices from a large user buffer, push is better, 950 * if index count is larger and we expect repeated vertices, suggest upload. 951 */ 952 nvc0->vbo_push_hint = 953 !info->indirect && info->indexed && 954 (nvc0->vb_elt_limit >= (info->count * 2)); 955 956 /* Check whether we want to switch vertex-submission mode. */ 957 if (nvc0->vbo_user && !(nvc0->dirty_3d & (NVC0_NEW_3D_ARRAYS | NVC0_NEW_3D_VERTEX))) { 958 if (nvc0->vbo_push_hint != !!nvc0->state.vbo_mode) 959 if (nvc0->state.vbo_mode != 3) 960 nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS; 961 962 if (!(nvc0->dirty_3d & NVC0_NEW_3D_ARRAYS) && nvc0->state.vbo_mode == 0) { 963 if (nvc0->vertex->shared_slots) 964 nvc0_update_user_vbufs_shared(nvc0); 965 else 966 nvc0_update_user_vbufs(nvc0); 967 } 968 } 969 970 if (info->mode == PIPE_PRIM_PATCHES && 971 nvc0->state.patch_vertices != info->vertices_per_patch) { 972 nvc0->state.patch_vertices = info->vertices_per_patch; 973 PUSH_SPACE(push, 1); 974 IMMED_NVC0(push, NVC0_3D(PATCH_VERTICES), nvc0->state.patch_vertices); 975 } 976 977 nvc0_state_validate_3d(nvc0, ~0); 978 979 if (nvc0->vertprog->vp.need_draw_parameters && !info->indirect) { 980 PUSH_SPACE(push, 9); 981 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 982 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 983 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 984 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 985 BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 3); 986 PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO); 987 PUSH_DATA (push, info->index_bias); 988 PUSH_DATA (push, info->start_instance); 989 PUSH_DATA (push, info->drawid); 990 } 991 992 if (nvc0->screen->base.class_3d < NVE4_3D_CLASS && 993 nvc0->seamless_cube_map != nvc0->state.seamless_cube_map) { 994 nvc0->state.seamless_cube_map = nvc0->seamless_cube_map; 995 PUSH_SPACE(push, 1); 996 IMMED_NVC0(push, NVC0_3D(TEX_MISC), 997 nvc0->seamless_cube_map ? NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP : 0); 998 } 999 1000 push->kick_notify = nvc0_draw_vbo_kick_notify; 1001 1002 for (s = 0; s < 5 && !nvc0->cb_dirty; ++s) { 1003 if (nvc0->constbuf_coherent[s]) 1004 nvc0->cb_dirty = true; 1005 } 1006 1007 if (nvc0->cb_dirty) { 1008 PUSH_SPACE(push, 1); 1009 IMMED_NVC0(push, NVC0_3D(MEM_BARRIER), 0x1011); 1010 nvc0->cb_dirty = false; 1011 } 1012 1013 for (s = 0; s < 5; ++s) { 1014 if (!nvc0->textures_coherent[s]) 1015 continue; 1016 1017 PUSH_SPACE(push, nvc0->num_textures[s] * 2); 1018 1019 for (int i = 0; i < nvc0->num_textures[s]; ++i) { 1020 struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]); 1021 if (!(nvc0->textures_coherent[s] & (1 << i))) 1022 continue; 1023 1024 BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 1025 PUSH_DATA (push, (tic->id << 4) | 1); 1026 NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_cache_flush_count, 1); 1027 } 1028 } 1029 1030 if (nvc0->state.vbo_mode) { 1031 nvc0_push_vbo(nvc0, info); 1032 push->kick_notify = nvc0_default_kick_notify; 1033 nouveau_pushbuf_bufctx(push, NULL); 1034 return; 1035 } 1036 1037 /* space for base instance, flush, and prim restart */ 1038 PUSH_SPACE(push, 8); 1039 1040 if (nvc0->state.instance_base != info->start_instance) { 1041 nvc0->state.instance_base = info->start_instance; 1042 /* NOTE: this does not affect the shader input, should it ? */ 1043 BEGIN_NVC0(push, NVC0_3D(VB_INSTANCE_BASE), 1); 1044 PUSH_DATA (push, info->start_instance); 1045 } 1046 1047 nvc0->base.vbo_dirty |= !!nvc0->vtxbufs_coherent; 1048 1049 if (!nvc0->base.vbo_dirty && nvc0->idxbuf.buffer && 1050 nvc0->idxbuf.buffer->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) 1051 nvc0->base.vbo_dirty = true; 1052 1053 nvc0_update_prim_restart(nvc0, info->primitive_restart, info->restart_index); 1054 1055 if (nvc0->base.vbo_dirty) { 1056 if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 1057 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 1058 nvc0->base.vbo_dirty = false; 1059 } 1060 1061 if (unlikely(info->indirect)) { 1062 nvc0_draw_indirect(nvc0, info); 1063 } else 1064 if (unlikely(info->count_from_stream_output)) { 1065 nvc0_draw_stream_output(nvc0, info); 1066 } else 1067 if (info->indexed) { 1068 bool shorten = info->max_index <= 65535; 1069 1070 if (info->primitive_restart && info->restart_index > 65535) 1071 shorten = false; 1072 1073 nvc0_draw_elements(nvc0, shorten, 1074 info->mode, info->start, info->count, 1075 info->instance_count, info->index_bias); 1076 } else { 1077 nvc0_draw_arrays(nvc0, 1078 info->mode, info->start, info->count, 1079 info->instance_count); 1080 } 1081 push->kick_notify = nvc0_default_kick_notify; 1082 1083 nvc0_release_user_vbufs(nvc0); 1084 1085 nouveau_pushbuf_bufctx(push, NULL); 1086 } 1087