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