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->buffer.user + ve->src_offset; 180 assert(vb->is_user_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->buffer.user, 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].buffer.user, 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.resource); 350 offset = ve->pipe.src_offset + vb->buffer_offset; 351 limit = vb->buffer.resource->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.resource) { 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.resource); 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 #define NVC0_PRIM_GL_CASE(n) \ 526 case PIPE_PRIM_##n: return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_##n 527 528 static inline unsigned 529 nvc0_prim_gl(unsigned prim) 530 { 531 switch (prim) { 532 NVC0_PRIM_GL_CASE(POINTS); 533 NVC0_PRIM_GL_CASE(LINES); 534 NVC0_PRIM_GL_CASE(LINE_LOOP); 535 NVC0_PRIM_GL_CASE(LINE_STRIP); 536 NVC0_PRIM_GL_CASE(TRIANGLES); 537 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP); 538 NVC0_PRIM_GL_CASE(TRIANGLE_FAN); 539 NVC0_PRIM_GL_CASE(QUADS); 540 NVC0_PRIM_GL_CASE(QUAD_STRIP); 541 NVC0_PRIM_GL_CASE(POLYGON); 542 NVC0_PRIM_GL_CASE(LINES_ADJACENCY); 543 NVC0_PRIM_GL_CASE(LINE_STRIP_ADJACENCY); 544 NVC0_PRIM_GL_CASE(TRIANGLES_ADJACENCY); 545 NVC0_PRIM_GL_CASE(TRIANGLE_STRIP_ADJACENCY); 546 NVC0_PRIM_GL_CASE(PATCHES); 547 default: 548 return NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_POINTS; 549 } 550 } 551 552 static void 553 nvc0_draw_vbo_kick_notify(struct nouveau_pushbuf *push) 554 { 555 struct nvc0_screen *screen = push->user_priv; 556 557 nouveau_fence_update(&screen->base, true); 558 559 NOUVEAU_DRV_STAT(&screen->base, pushbuf_count, 1); 560 } 561 562 static void 563 nvc0_draw_arrays(struct nvc0_context *nvc0, 564 unsigned mode, unsigned start, unsigned count, 565 unsigned instance_count) 566 { 567 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 568 unsigned prim; 569 570 if (nvc0->state.index_bias) { 571 /* index_bias is implied 0 if !info->index_size (really ?) */ 572 /* TODO: can we deactivate it for the VERTEX_BUFFER_FIRST command ? */ 573 PUSH_SPACE(push, 2); 574 IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 575 IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 576 nvc0->state.index_bias = 0; 577 } 578 579 prim = nvc0_prim_gl(mode); 580 581 while (instance_count--) { 582 PUSH_SPACE(push, 6); 583 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 584 PUSH_DATA (push, prim); 585 BEGIN_NVC0(push, NVC0_3D(VERTEX_BUFFER_FIRST), 2); 586 PUSH_DATA (push, start); 587 PUSH_DATA (push, count); 588 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 589 590 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 591 } 592 NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_array, 1); 593 } 594 595 static void 596 nvc0_draw_elements_inline_u08(struct nouveau_pushbuf *push, const uint8_t *map, 597 unsigned start, unsigned count) 598 { 599 map += start; 600 601 if (count & 3) { 602 unsigned i; 603 PUSH_SPACE(push, 4); 604 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), count & 3); 605 for (i = 0; i < (count & 3); ++i) 606 PUSH_DATA(push, *map++); 607 count &= ~3; 608 } 609 while (count) { 610 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 4) / 4; 611 612 PUSH_SPACE(push, nr + 1); 613 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U8), nr); 614 for (i = 0; i < nr; ++i) { 615 PUSH_DATA(push, 616 (map[3] << 24) | (map[2] << 16) | (map[1] << 8) | map[0]); 617 map += 4; 618 } 619 count -= nr * 4; 620 } 621 } 622 623 static void 624 nvc0_draw_elements_inline_u16(struct nouveau_pushbuf *push, const uint16_t *map, 625 unsigned start, unsigned count) 626 { 627 map += start; 628 629 if (count & 1) { 630 count &= ~1; 631 PUSH_SPACE(push, 2); 632 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 633 PUSH_DATA (push, *map++); 634 } 635 while (count) { 636 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 637 638 PUSH_SPACE(push, nr + 1); 639 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 640 for (i = 0; i < nr; ++i) { 641 PUSH_DATA(push, (map[1] << 16) | map[0]); 642 map += 2; 643 } 644 count -= nr * 2; 645 } 646 } 647 648 static void 649 nvc0_draw_elements_inline_u32(struct nouveau_pushbuf *push, const uint32_t *map, 650 unsigned start, unsigned count) 651 { 652 map += start; 653 654 while (count) { 655 const unsigned nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); 656 657 PUSH_SPACE(push, nr + 1); 658 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U32), nr); 659 PUSH_DATAp(push, map, nr); 660 661 map += nr; 662 count -= nr; 663 } 664 } 665 666 static void 667 nvc0_draw_elements_inline_u32_short(struct nouveau_pushbuf *push, 668 const uint32_t *map, 669 unsigned start, unsigned count) 670 { 671 map += start; 672 673 if (count & 1) { 674 count--; 675 PUSH_SPACE(push, 2); 676 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_U32), 1); 677 PUSH_DATA (push, *map++); 678 } 679 while (count) { 680 unsigned i, nr = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN * 2) / 2; 681 682 PUSH_SPACE(push, nr + 1); 683 BEGIN_NIC0(push, NVC0_3D(VB_ELEMENT_U16), nr); 684 for (i = 0; i < nr; ++i) { 685 PUSH_DATA(push, (map[1] << 16) | map[0]); 686 map += 2; 687 } 688 count -= nr * 2; 689 } 690 } 691 692 static void 693 nvc0_draw_elements(struct nvc0_context *nvc0, bool shorten, 694 const struct pipe_draw_info *info, 695 unsigned mode, unsigned start, unsigned count, 696 unsigned instance_count, int32_t index_bias, 697 unsigned index_size) 698 { 699 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 700 unsigned prim; 701 702 prim = nvc0_prim_gl(mode); 703 704 if (index_bias != nvc0->state.index_bias) { 705 PUSH_SPACE(push, 4); 706 BEGIN_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 1); 707 PUSH_DATA (push, index_bias); 708 BEGIN_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 1); 709 PUSH_DATA (push, index_bias); 710 nvc0->state.index_bias = index_bias; 711 } 712 713 if (!info->has_user_indices) { 714 PUSH_SPACE(push, 1); 715 IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), prim); 716 do { 717 PUSH_SPACE(push, 7); 718 BEGIN_NVC0(push, NVC0_3D(INDEX_BATCH_FIRST), 2); 719 PUSH_DATA (push, start); 720 PUSH_DATA (push, count); 721 if (--instance_count) { 722 BEGIN_NVC0(push, NVC0_3D(VERTEX_END_GL), 2); 723 PUSH_DATA (push, 0); 724 PUSH_DATA (push, prim | NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT); 725 } 726 } while (instance_count); 727 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 728 } else { 729 const void *data = info->index.user; 730 731 while (instance_count--) { 732 PUSH_SPACE(push, 2); 733 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 734 PUSH_DATA (push, prim); 735 switch (index_size) { 736 case 1: 737 nvc0_draw_elements_inline_u08(push, data, start, count); 738 break; 739 case 2: 740 nvc0_draw_elements_inline_u16(push, data, start, count); 741 break; 742 case 4: 743 if (shorten) 744 nvc0_draw_elements_inline_u32_short(push, data, start, count); 745 else 746 nvc0_draw_elements_inline_u32(push, data, start, count); 747 break; 748 default: 749 assert(0); 750 return; 751 } 752 PUSH_SPACE(push, 1); 753 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 754 755 prim |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 756 } 757 } 758 NOUVEAU_DRV_STAT(&nvc0->screen->base, draw_calls_indexed, 1); 759 } 760 761 static void 762 nvc0_draw_stream_output(struct nvc0_context *nvc0, 763 const struct pipe_draw_info *info) 764 { 765 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 766 struct nvc0_so_target *so = nvc0_so_target(info->count_from_stream_output); 767 struct nv04_resource *res = nv04_resource(so->pipe.buffer); 768 unsigned mode = nvc0_prim_gl(info->mode); 769 unsigned num_instances = info->instance_count; 770 771 if (res->status & NOUVEAU_BUFFER_STATUS_GPU_WRITING) { 772 res->status &= ~NOUVEAU_BUFFER_STATUS_GPU_WRITING; 773 PUSH_SPACE(push, 2); 774 IMMED_NVC0(push, NVC0_3D(SERIALIZE), 0); 775 nvc0_hw_query_fifo_wait(nvc0, nvc0_query(so->pq)); 776 if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 777 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 778 779 NOUVEAU_DRV_STAT(&nvc0->screen->base, gpu_serialize_count, 1); 780 } 781 782 while (num_instances--) { 783 nouveau_pushbuf_space(push, 16, 0, 1); 784 BEGIN_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL), 1); 785 PUSH_DATA (push, mode); 786 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BASE), 1); 787 PUSH_DATA (push, 0); 788 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_STRIDE), 1); 789 PUSH_DATA (push, so->stride); 790 BEGIN_NVC0(push, NVC0_3D(DRAW_TFB_BYTES), 1); 791 nvc0_hw_query_pushbuf_submit(push, nvc0_query(so->pq), 0x4); 792 IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0); 793 794 mode |= NVC0_3D_VERTEX_BEGIN_GL_INSTANCE_NEXT; 795 } 796 } 797 798 static void 799 nvc0_draw_indirect(struct nvc0_context *nvc0, const struct pipe_draw_info *info) 800 { 801 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 802 struct nv04_resource *buf = nv04_resource(info->indirect->buffer); 803 struct nv04_resource *buf_count = nv04_resource(info->indirect->indirect_draw_count); 804 unsigned size, macro, count = info->indirect->draw_count, drawid = info->drawid; 805 uint32_t offset = buf->offset + info->indirect->offset; 806 struct nvc0_screen *screen = nvc0->screen; 807 808 PUSH_SPACE(push, 7); 809 810 /* must make FIFO wait for engines idle before continuing to process */ 811 if ((buf->fence_wr && !nouveau_fence_signalled(buf->fence_wr)) || 812 (buf_count && buf_count->fence_wr && 813 !nouveau_fence_signalled(buf_count->fence_wr))) { 814 IMMED_NVC0(push, SUBC_3D(NV10_SUBCHAN_REF_CNT), 0); 815 } 816 817 /* Queue things up to let the macros write params to the driver constbuf */ 818 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 819 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 820 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 821 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 822 BEGIN_NVC0(push, NVC0_3D(CB_POS), 1); 823 PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO); 824 825 if (info->index_size) { 826 assert(!info->has_user_indices); 827 assert(nouveau_resource_mapped_by_gpu(info->index.resource)); 828 size = 5; 829 if (buf_count) 830 macro = NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT_COUNT; 831 else 832 macro = NVC0_3D_MACRO_DRAW_ELEMENTS_INDIRECT; 833 } else { 834 if (nvc0->state.index_bias) { 835 /* index_bias is implied 0 if !info->index_size (really ?) */ 836 IMMED_NVC0(push, NVC0_3D(VB_ELEMENT_BASE), 0); 837 IMMED_NVC0(push, NVC0_3D(VERTEX_ID_BASE), 0); 838 nvc0->state.index_bias = 0; 839 } 840 size = 4; 841 if (buf_count) 842 macro = NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT_COUNT; 843 else 844 macro = NVC0_3D_MACRO_DRAW_ARRAYS_INDIRECT; 845 } 846 847 /* If the stride is not the natural stride, we have to stick a separate 848 * push data reference for each draw. Otherwise it can all go in as one. 849 * Of course there is a maximum packet size, so we have to break things up 850 * along those borders as well. 851 */ 852 while (count) { 853 unsigned draws = count, pushes, i; 854 if (info->indirect->stride == size * 4) { 855 draws = MIN2(draws, (NV04_PFIFO_MAX_PACKET_LEN - 4) / size); 856 pushes = 1; 857 } else { 858 draws = MIN2(draws, 32); 859 pushes = draws; 860 } 861 862 nouveau_pushbuf_space(push, 16, 0, pushes + !!buf_count); 863 PUSH_REFN(push, buf->bo, NOUVEAU_BO_RD | buf->domain); 864 if (buf_count) 865 PUSH_REFN(push, buf_count->bo, NOUVEAU_BO_RD | buf_count->domain); 866 PUSH_DATA(push, 867 NVC0_FIFO_PKHDR_1I(0, macro, 3 + !!buf_count + draws * size)); 868 PUSH_DATA(push, nvc0_prim_gl(info->mode)); 869 PUSH_DATA(push, drawid); 870 PUSH_DATA(push, draws); 871 if (buf_count) { 872 nouveau_pushbuf_data(push, 873 buf_count->bo, 874 buf_count->offset + info->indirect->indirect_draw_count_offset, 875 NVC0_IB_ENTRY_1_NO_PREFETCH | 4); 876 } 877 if (pushes == 1) { 878 nouveau_pushbuf_data(push, 879 buf->bo, offset, 880 NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4 * draws)); 881 offset += draws * info->indirect->stride; 882 } else { 883 for (i = 0; i < pushes; i++) { 884 nouveau_pushbuf_data(push, 885 buf->bo, offset, 886 NVC0_IB_ENTRY_1_NO_PREFETCH | (size * 4)); 887 offset += info->indirect->stride; 888 } 889 } 890 count -= draws; 891 drawid += draws; 892 } 893 } 894 895 static inline void 896 nvc0_update_prim_restart(struct nvc0_context *nvc0, bool en, uint32_t index) 897 { 898 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 899 900 if (en != nvc0->state.prim_restart) { 901 if (en) { 902 BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 2); 903 PUSH_DATA (push, 1); 904 PUSH_DATA (push, index); 905 } else { 906 IMMED_NVC0(push, NVC0_3D(PRIM_RESTART_ENABLE), 0); 907 } 908 nvc0->state.prim_restart = en; 909 } else 910 if (en) { 911 BEGIN_NVC0(push, NVC0_3D(PRIM_RESTART_INDEX), 1); 912 PUSH_DATA (push, index); 913 } 914 } 915 916 void 917 nvc0_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info) 918 { 919 struct nvc0_context *nvc0 = nvc0_context(pipe); 920 struct nouveau_pushbuf *push = nvc0->base.pushbuf; 921 struct nvc0_screen *screen = nvc0->screen; 922 int s; 923 924 /* NOTE: caller must ensure that (min_index + index_bias) is >= 0 */ 925 nvc0->vb_elt_first = info->min_index + info->index_bias; 926 nvc0->vb_elt_limit = info->max_index - info->min_index; 927 nvc0->instance_off = info->start_instance; 928 nvc0->instance_max = info->instance_count - 1; 929 930 /* For picking only a few vertices from a large user buffer, push is better, 931 * if index count is larger and we expect repeated vertices, suggest upload. 932 */ 933 nvc0->vbo_push_hint = 934 !info->indirect && info->index_size && 935 (nvc0->vb_elt_limit >= (info->count * 2)); 936 937 /* Check whether we want to switch vertex-submission mode. */ 938 if (nvc0->vbo_user && !(nvc0->dirty_3d & (NVC0_NEW_3D_ARRAYS | NVC0_NEW_3D_VERTEX))) { 939 if (nvc0->vbo_push_hint != !!nvc0->state.vbo_mode) 940 if (nvc0->state.vbo_mode != 3) 941 nvc0->dirty_3d |= NVC0_NEW_3D_ARRAYS; 942 943 if (!(nvc0->dirty_3d & NVC0_NEW_3D_ARRAYS) && nvc0->state.vbo_mode == 0) { 944 if (nvc0->vertex->shared_slots) 945 nvc0_update_user_vbufs_shared(nvc0); 946 else 947 nvc0_update_user_vbufs(nvc0); 948 } 949 } 950 951 if (info->mode == PIPE_PRIM_PATCHES && 952 nvc0->state.patch_vertices != info->vertices_per_patch) { 953 nvc0->state.patch_vertices = info->vertices_per_patch; 954 PUSH_SPACE(push, 1); 955 IMMED_NVC0(push, NVC0_3D(PATCH_VERTICES), nvc0->state.patch_vertices); 956 } 957 958 if (info->index_size && !info->has_user_indices) { 959 struct nv04_resource *buf = nv04_resource(info->index.resource); 960 961 assert(buf); 962 assert(nouveau_resource_mapped_by_gpu(&buf->base)); 963 964 PUSH_SPACE(push, 6); 965 BEGIN_NVC0(push, NVC0_3D(INDEX_ARRAY_START_HIGH), 5); 966 PUSH_DATAh(push, buf->address); 967 PUSH_DATA (push, buf->address); 968 PUSH_DATAh(push, buf->address + buf->base.width0 - 1); 969 PUSH_DATA (push, buf->address + buf->base.width0 - 1); 970 PUSH_DATA (push, info->index_size >> 1); 971 972 BCTX_REFN(nvc0->bufctx_3d, 3D_IDX, buf, RD); 973 } 974 975 list_for_each_entry(struct nvc0_resident, resident, &nvc0->tex_head, list) { 976 nvc0_add_resident(nvc0->bufctx_3d, NVC0_BIND_3D_BINDLESS, resident->buf, 977 resident->flags); 978 } 979 980 list_for_each_entry(struct nvc0_resident, resident, &nvc0->img_head, list) { 981 nvc0_add_resident(nvc0->bufctx_3d, NVC0_BIND_3D_BINDLESS, resident->buf, 982 resident->flags); 983 } 984 985 nvc0_state_validate_3d(nvc0, ~0); 986 987 if (nvc0->vertprog->vp.need_draw_parameters && !info->indirect) { 988 PUSH_SPACE(push, 9); 989 BEGIN_NVC0(push, NVC0_3D(CB_SIZE), 3); 990 PUSH_DATA (push, NVC0_CB_AUX_SIZE); 991 PUSH_DATAh(push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 992 PUSH_DATA (push, screen->uniform_bo->offset + NVC0_CB_AUX_INFO(0)); 993 BEGIN_1IC0(push, NVC0_3D(CB_POS), 1 + 3); 994 PUSH_DATA (push, NVC0_CB_AUX_DRAW_INFO); 995 PUSH_DATA (push, info->index_bias); 996 PUSH_DATA (push, info->start_instance); 997 PUSH_DATA (push, info->drawid); 998 } 999 1000 if (nvc0->screen->base.class_3d < NVE4_3D_CLASS && 1001 nvc0->seamless_cube_map != nvc0->state.seamless_cube_map) { 1002 nvc0->state.seamless_cube_map = nvc0->seamless_cube_map; 1003 PUSH_SPACE(push, 1); 1004 IMMED_NVC0(push, NVC0_3D(TEX_MISC), 1005 nvc0->seamless_cube_map ? NVC0_3D_TEX_MISC_SEAMLESS_CUBE_MAP : 0); 1006 } 1007 1008 push->kick_notify = nvc0_draw_vbo_kick_notify; 1009 1010 for (s = 0; s < 5 && !nvc0->cb_dirty; ++s) { 1011 if (nvc0->constbuf_coherent[s]) 1012 nvc0->cb_dirty = true; 1013 } 1014 1015 if (nvc0->cb_dirty) { 1016 PUSH_SPACE(push, 1); 1017 IMMED_NVC0(push, NVC0_3D(MEM_BARRIER), 0x1011); 1018 nvc0->cb_dirty = false; 1019 } 1020 1021 for (s = 0; s < 5; ++s) { 1022 if (!nvc0->textures_coherent[s]) 1023 continue; 1024 1025 PUSH_SPACE(push, nvc0->num_textures[s] * 2); 1026 1027 for (int i = 0; i < nvc0->num_textures[s]; ++i) { 1028 struct nv50_tic_entry *tic = nv50_tic_entry(nvc0->textures[s][i]); 1029 if (!(nvc0->textures_coherent[s] & (1 << i))) 1030 continue; 1031 1032 BEGIN_NVC0(push, NVC0_3D(TEX_CACHE_CTL), 1); 1033 PUSH_DATA (push, (tic->id << 4) | 1); 1034 NOUVEAU_DRV_STAT(&nvc0->screen->base, tex_cache_flush_count, 1); 1035 } 1036 } 1037 1038 if (nvc0->state.vbo_mode) { 1039 nvc0_push_vbo(nvc0, info); 1040 goto cleanup; 1041 } 1042 1043 /* space for base instance, flush, and prim restart */ 1044 PUSH_SPACE(push, 8); 1045 1046 if (nvc0->state.instance_base != info->start_instance) { 1047 nvc0->state.instance_base = info->start_instance; 1048 /* NOTE: this does not affect the shader input, should it ? */ 1049 BEGIN_NVC0(push, NVC0_3D(VB_INSTANCE_BASE), 1); 1050 PUSH_DATA (push, info->start_instance); 1051 } 1052 1053 nvc0->base.vbo_dirty |= !!nvc0->vtxbufs_coherent; 1054 1055 if (!nvc0->base.vbo_dirty && info->index_size && !info->has_user_indices && 1056 info->index.resource->flags & PIPE_RESOURCE_FLAG_MAP_COHERENT) 1057 nvc0->base.vbo_dirty = true; 1058 1059 nvc0_update_prim_restart(nvc0, info->primitive_restart, info->restart_index); 1060 1061 if (nvc0->base.vbo_dirty) { 1062 if (nvc0->screen->eng3d->oclass < GM107_3D_CLASS) 1063 IMMED_NVC0(push, NVC0_3D(VERTEX_ARRAY_FLUSH), 0); 1064 nvc0->base.vbo_dirty = false; 1065 } 1066 1067 if (unlikely(info->indirect)) { 1068 nvc0_draw_indirect(nvc0, info); 1069 } else 1070 if (unlikely(info->count_from_stream_output)) { 1071 nvc0_draw_stream_output(nvc0, info); 1072 } else 1073 if (info->index_size) { 1074 bool shorten = info->max_index <= 65535; 1075 1076 if (info->primitive_restart && info->restart_index > 65535) 1077 shorten = false; 1078 1079 nvc0_draw_elements(nvc0, shorten, info, 1080 info->mode, info->start, info->count, 1081 info->instance_count, info->index_bias, info->index_size); 1082 } else { 1083 nvc0_draw_arrays(nvc0, 1084 info->mode, info->start, info->count, 1085 info->instance_count); 1086 } 1087 1088 cleanup: 1089 push->kick_notify = nvc0_default_kick_notify; 1090 1091 nvc0_release_user_vbufs(nvc0); 1092 1093 nouveau_pushbuf_bufctx(push, NULL); 1094 1095 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_IDX); 1096 nouveau_bufctx_reset(nvc0->bufctx_3d, NVC0_BIND_3D_BINDLESS); 1097 } 1098