u_vbuf.c revision 889238c8b1e6b8ac5eed30ec3122be94216ca7cf
1/************************************************************************** 2 * 3 * Copyright 2011 Marek Olšák <maraeo@gmail.com> 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28#include "util/u_vbuf.h" 29 30#include "util/u_dump.h" 31#include "util/u_format.h" 32#include "util/u_inlines.h" 33#include "util/u_memory.h" 34#include "util/u_upload_mgr.h" 35#include "translate/translate.h" 36#include "translate/translate_cache.h" 37#include "cso_cache/cso_cache.h" 38#include "cso_cache/cso_hash.h" 39 40struct u_vbuf_elements { 41 unsigned count; 42 struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS]; 43 44 unsigned src_format_size[PIPE_MAX_ATTRIBS]; 45 46 /* If (velem[i].src_format != native_format[i]), the vertex buffer 47 * referenced by the vertex element cannot be used for rendering and 48 * its vertex data must be translated to native_format[i]. */ 49 enum pipe_format native_format[PIPE_MAX_ATTRIBS]; 50 unsigned native_format_size[PIPE_MAX_ATTRIBS]; 51 52 /* This might mean two things: 53 * - src_format != native_format, as discussed above. 54 * - src_offset % 4 != 0 (if the caps don't allow such an offset). */ 55 boolean incompatible_layout; 56 /* Per-element flags. */ 57 boolean incompatible_layout_elem[PIPE_MAX_ATTRIBS]; 58 59 void *driver_cso; 60}; 61 62enum { 63 VB_VERTEX = 0, 64 VB_INSTANCE = 1, 65 VB_CONST = 2, 66 VB_NUM = 3 67}; 68 69struct u_vbuf_priv { 70 struct u_vbuf b; 71 struct pipe_context *pipe; 72 struct translate_cache *translate_cache; 73 struct cso_cache *cso_cache; 74 75 /* Vertex buffers for the driver. 76 * There are no user buffers. */ 77 struct pipe_vertex_buffer real_vertex_buffer[PIPE_MAX_ATTRIBS]; 78 int nr_real_vertex_buffers; 79 80 /* The index buffer. */ 81 struct pipe_index_buffer index_buffer; 82 83 /* and its associated helper structure for this module. */ 84 struct u_vbuf_elements *ve; 85 86 /* Vertex elements used for the translate fallback. */ 87 struct pipe_vertex_element fallback_velems[PIPE_MAX_ATTRIBS]; 88 /* If non-NULL, this is a vertex element state used for the translate 89 * fallback and therefore used for rendering too. */ 90 void *fallback_ve; 91 /* The vertex buffer slot index where translated vertices have been 92 * stored in. */ 93 unsigned fallback_vbs[VB_NUM]; 94 95 /* Whether there is any user buffer. */ 96 boolean any_user_vbs; 97 /* Whether there is a buffer with a non-native layout. */ 98 boolean incompatible_vb_layout; 99 /* Per-buffer flags. */ 100 boolean incompatible_vb[PIPE_MAX_ATTRIBS]; 101 102 void (*driver_set_index_buffer)(struct pipe_context *pipe, 103 const struct pipe_index_buffer *); 104 void (*driver_set_vertex_buffers)(struct pipe_context *, 105 unsigned num_buffers, 106 const struct pipe_vertex_buffer *); 107 void *(*driver_create_vertex_elements_state)(struct pipe_context *, 108 unsigned num_elements, 109 const struct pipe_vertex_element *); 110 void (*driver_bind_vertex_elements_state)(struct pipe_context *, void *); 111 void (*driver_delete_vertex_elements_state)(struct pipe_context *, void *); 112}; 113 114static void u_vbuf_init_format_caps(struct u_vbuf_priv *mgr) 115{ 116 struct pipe_screen *screen = mgr->pipe->screen; 117 118 mgr->b.caps.format_fixed32 = 119 screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER, 120 0, PIPE_BIND_VERTEX_BUFFER); 121 122 mgr->b.caps.format_float16 = 123 screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER, 124 0, PIPE_BIND_VERTEX_BUFFER); 125 126 mgr->b.caps.format_float64 = 127 screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER, 128 0, PIPE_BIND_VERTEX_BUFFER); 129 130 mgr->b.caps.format_norm32 = 131 screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER, 132 0, PIPE_BIND_VERTEX_BUFFER) && 133 screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER, 134 0, PIPE_BIND_VERTEX_BUFFER); 135 136 mgr->b.caps.format_scaled32 = 137 screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER, 138 0, PIPE_BIND_VERTEX_BUFFER) && 139 screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER, 140 0, PIPE_BIND_VERTEX_BUFFER); 141} 142 143static void u_vbuf_install(struct u_vbuf_priv *mgr); 144 145struct u_vbuf * 146u_vbuf_create(struct pipe_context *pipe, 147 unsigned upload_buffer_size, 148 unsigned upload_buffer_alignment, 149 unsigned upload_buffer_bind, 150 enum u_fetch_alignment fetch_alignment) 151{ 152 struct u_vbuf_priv *mgr = CALLOC_STRUCT(u_vbuf_priv); 153 154 mgr->pipe = pipe; 155 mgr->cso_cache = cso_cache_create(); 156 mgr->translate_cache = translate_cache_create(); 157 memset(mgr->fallback_vbs, ~0, sizeof(mgr->fallback_vbs)); 158 159 mgr->b.uploader = u_upload_create(pipe, upload_buffer_size, 160 upload_buffer_alignment, 161 upload_buffer_bind); 162 163 mgr->b.caps.fetch_dword_unaligned = 164 fetch_alignment == U_VERTEX_FETCH_BYTE_ALIGNED; 165 166 u_vbuf_init_format_caps(mgr); 167 u_vbuf_install(mgr); 168 return &mgr->b; 169} 170 171/* XXX I had to fork this off of cso_context. */ 172static void * 173u_vbuf_cache_set_vertex_elements(struct u_vbuf_priv *mgr, 174 unsigned count, 175 const struct pipe_vertex_element *states) 176{ 177 unsigned key_size, hash_key; 178 struct cso_hash_iter iter; 179 void *handle; 180 struct cso_velems_state velems_state; 181 182 /* need to include the count into the stored state data too. */ 183 key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned); 184 velems_state.count = count; 185 memcpy(velems_state.velems, states, 186 sizeof(struct pipe_vertex_element) * count); 187 hash_key = cso_construct_key((void*)&velems_state, key_size); 188 iter = cso_find_state_template(mgr->cso_cache, hash_key, CSO_VELEMENTS, 189 (void*)&velems_state, key_size); 190 191 if (cso_hash_iter_is_null(iter)) { 192 struct cso_velements *cso = MALLOC_STRUCT(cso_velements); 193 memcpy(&cso->state, &velems_state, key_size); 194 cso->data = 195 mgr->driver_create_vertex_elements_state(mgr->pipe, count, 196 &cso->state.velems[0]); 197 cso->delete_state = 198 (cso_state_callback)mgr->driver_delete_vertex_elements_state; 199 cso->context = mgr->pipe; 200 201 iter = cso_insert_state(mgr->cso_cache, hash_key, CSO_VELEMENTS, cso); 202 handle = cso->data; 203 } else { 204 handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data; 205 } 206 207 mgr->driver_bind_vertex_elements_state(mgr->pipe, handle); 208 return handle; 209} 210 211void u_vbuf_destroy(struct u_vbuf *mgrb) 212{ 213 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; 214 unsigned i; 215 216 assert(mgr->pipe->draw); 217 mgr->pipe->draw = NULL; 218 219 for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { 220 pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); 221 } 222 for (i = 0; i < mgr->nr_real_vertex_buffers; i++) { 223 pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL); 224 } 225 226 translate_cache_destroy(mgr->translate_cache); 227 u_upload_destroy(mgr->b.uploader); 228 cso_cache_delete(mgr->cso_cache); 229 FREE(mgr); 230} 231 232static void 233u_vbuf_translate_buffers(struct u_vbuf_priv *mgr, struct translate_key *key, 234 unsigned vb_mask, unsigned out_vb, 235 int start_vertex, unsigned num_vertices, 236 int start_index, unsigned num_indices, int min_index, 237 bool unroll_indices) 238{ 239 struct translate *tr; 240 struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0}; 241 struct pipe_resource *out_buffer = NULL; 242 uint8_t *out_map; 243 unsigned i, out_offset; 244 245 /* Get a translate object. */ 246 tr = translate_cache_find(mgr->translate_cache, key); 247 248 /* Map buffers we want to translate. */ 249 for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { 250 if (vb_mask & (1 << i)) { 251 struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[i]; 252 unsigned offset = vb->buffer_offset + vb->stride * start_vertex; 253 uint8_t *map; 254 255 if (u_vbuf_resource(vb->buffer)->user_ptr) { 256 map = u_vbuf_resource(vb->buffer)->user_ptr + offset; 257 } else { 258 unsigned size = vb->stride ? num_vertices * vb->stride 259 : sizeof(double)*4; 260 261 if (offset+size > vb->buffer->width0) { 262 size = vb->buffer->width0 - offset; 263 } 264 265 map = pipe_buffer_map_range(mgr->pipe, vb->buffer, offset, size, 266 PIPE_TRANSFER_READ, &vb_transfer[i]); 267 } 268 269 /* Subtract min_index so that indexing with the index buffer works. */ 270 if (unroll_indices) { 271 map -= vb->stride * min_index; 272 } 273 274 tr->set_buffer(tr, i, map, vb->stride, ~0); 275 } 276 } 277 278 /* Translate. */ 279 if (unroll_indices) { 280 struct pipe_index_buffer *ib = &mgr->index_buffer; 281 struct pipe_transfer *transfer = NULL; 282 unsigned offset = ib->offset + start_index * ib->index_size; 283 uint8_t *map; 284 285 assert(ib->buffer && ib->index_size); 286 287 if (u_vbuf_resource(ib->buffer)->user_ptr) { 288 map = u_vbuf_resource(ib->buffer)->user_ptr + offset; 289 } else { 290 map = pipe_buffer_map_range(mgr->pipe, ib->buffer, offset, 291 num_indices * ib->index_size, 292 PIPE_TRANSFER_READ, &transfer); 293 } 294 295 /* Create and map the output buffer. */ 296 u_upload_alloc(mgr->b.uploader, 0, 297 key->output_stride * num_indices, 298 &out_offset, &out_buffer, 299 (void**)&out_map); 300 301 switch (ib->index_size) { 302 case 4: 303 tr->run_elts(tr, (unsigned*)map, num_indices, 0, out_map); 304 break; 305 case 2: 306 tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, out_map); 307 break; 308 case 1: 309 tr->run_elts8(tr, map, num_indices, 0, out_map); 310 break; 311 } 312 313 if (transfer) { 314 pipe_buffer_unmap(mgr->pipe, transfer); 315 } 316 } else { 317 /* Create and map the output buffer. */ 318 u_upload_alloc(mgr->b.uploader, 319 key->output_stride * start_vertex, 320 key->output_stride * num_vertices, 321 &out_offset, &out_buffer, 322 (void**)&out_map); 323 324 out_offset -= key->output_stride * start_vertex; 325 326 tr->run(tr, 0, num_vertices, 0, out_map); 327 } 328 329 /* Unmap all buffers. */ 330 for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { 331 if (vb_transfer[i]) { 332 pipe_buffer_unmap(mgr->pipe, vb_transfer[i]); 333 } 334 } 335 336 /* Setup the new vertex buffer. */ 337 mgr->real_vertex_buffer[out_vb].buffer_offset = out_offset; 338 mgr->real_vertex_buffer[out_vb].stride = key->output_stride; 339 340 /* Move the buffer reference. */ 341 pipe_resource_reference( 342 &mgr->real_vertex_buffer[out_vb].buffer, NULL); 343 mgr->real_vertex_buffer[out_vb].buffer = out_buffer; 344} 345 346static boolean 347u_vbuf_translate_find_free_vb_slots(struct u_vbuf_priv *mgr, 348 unsigned mask[VB_NUM]) 349{ 350 unsigned i, type; 351 unsigned nr = mgr->ve->count; 352 boolean used_vb[PIPE_MAX_ATTRIBS] = {0}; 353 unsigned fallback_vbs[VB_NUM]; 354 355 memset(fallback_vbs, ~0, sizeof(fallback_vbs)); 356 357 /* Mark used vertex buffers as... used. */ 358 for (i = 0; i < nr; i++) { 359 if (!mgr->ve->incompatible_layout_elem[i]) { 360 unsigned index = mgr->ve->ve[i].vertex_buffer_index; 361 362 if (!mgr->incompatible_vb[index]) { 363 used_vb[index] = TRUE; 364 } 365 } 366 } 367 368 /* Find free slots for each type if needed. */ 369 i = 0; 370 for (type = 0; type < VB_NUM; type++) { 371 if (mask[type]) { 372 for (; i < PIPE_MAX_ATTRIBS; i++) { 373 if (!used_vb[i]) { 374 /*printf("found slot=%i for type=%i\n", i, type);*/ 375 fallback_vbs[type] = i; 376 i++; 377 if (i > mgr->nr_real_vertex_buffers) { 378 mgr->nr_real_vertex_buffers = i; 379 } 380 break; 381 } 382 } 383 if (i == PIPE_MAX_ATTRIBS) { 384 /* fail, reset the number to its original value */ 385 mgr->nr_real_vertex_buffers = mgr->b.nr_vertex_buffers; 386 return FALSE; 387 } 388 } 389 } 390 391 memcpy(mgr->fallback_vbs, fallback_vbs, sizeof(fallback_vbs)); 392 return TRUE; 393} 394 395static boolean 396u_vbuf_translate_begin(struct u_vbuf_priv *mgr, 397 int start_vertex, unsigned num_vertices, 398 int start_instance, unsigned num_instances, 399 int start_index, unsigned num_indices, int min_index, 400 bool unroll_indices) 401{ 402 unsigned mask[VB_NUM] = {0}; 403 struct translate_key key[VB_NUM]; 404 unsigned elem_index[VB_NUM][PIPE_MAX_ATTRIBS]; /* ... into key.elements */ 405 unsigned i, type; 406 407 int start[VB_NUM] = { 408 start_vertex, /* VERTEX */ 409 start_instance, /* INSTANCE */ 410 0 /* CONST */ 411 }; 412 413 unsigned num[VB_NUM] = { 414 num_vertices, /* VERTEX */ 415 num_instances, /* INSTANCE */ 416 1 /* CONST */ 417 }; 418 419 memset(key, 0, sizeof(key)); 420 memset(elem_index, ~0, sizeof(elem_index)); 421 422 /* See if there are vertex attribs of each type to translate and 423 * which ones. */ 424 for (i = 0; i < mgr->ve->count; i++) { 425 unsigned vb_index = mgr->ve->ve[i].vertex_buffer_index; 426 427 if (!mgr->b.vertex_buffer[vb_index].stride) { 428 if (!mgr->ve->incompatible_layout_elem[i] && 429 !mgr->incompatible_vb[vb_index]) { 430 continue; 431 } 432 mask[VB_CONST] |= 1 << vb_index; 433 } else if (mgr->ve->ve[i].instance_divisor) { 434 if (!mgr->ve->incompatible_layout_elem[i] && 435 !mgr->incompatible_vb[vb_index]) { 436 continue; 437 } 438 mask[VB_INSTANCE] |= 1 << vb_index; 439 } else { 440 if (!unroll_indices && 441 !mgr->ve->incompatible_layout_elem[i] && 442 !mgr->incompatible_vb[vb_index]) { 443 continue; 444 } 445 mask[VB_VERTEX] |= 1 << vb_index; 446 } 447 } 448 449 assert(mask[VB_VERTEX] || mask[VB_INSTANCE] || mask[VB_CONST]); 450 451 /* Find free vertex buffer slots. */ 452 if (!u_vbuf_translate_find_free_vb_slots(mgr, mask)) { 453 return FALSE; 454 } 455 456 /* Initialize the translate keys. */ 457 for (i = 0; i < mgr->ve->count; i++) { 458 struct translate_key *k; 459 struct translate_element *te; 460 unsigned bit, vb_index = mgr->ve->ve[i].vertex_buffer_index; 461 bit = 1 << vb_index; 462 463 if (!mgr->ve->incompatible_layout_elem[i] && 464 !mgr->incompatible_vb[vb_index] && 465 (!unroll_indices || !(mask[VB_VERTEX] & bit))) { 466 continue; 467 } 468 469 /* Set type to what we will translate. 470 * Whether vertex, instance, or constant attribs. */ 471 for (type = 0; type < VB_NUM; type++) { 472 if (mask[type] & bit) { 473 break; 474 } 475 } 476 assert(type < VB_NUM); 477 assert(translate_is_output_format_supported(mgr->ve->native_format[i])); 478 /*printf("velem=%i type=%i\n", i, type);*/ 479 480 /* Add the vertex element. */ 481 k = &key[type]; 482 elem_index[type][i] = k->nr_elements; 483 484 te = &k->element[k->nr_elements]; 485 te->type = TRANSLATE_ELEMENT_NORMAL; 486 te->instance_divisor = 0; 487 te->input_buffer = vb_index; 488 te->input_format = mgr->ve->ve[i].src_format; 489 te->input_offset = mgr->ve->ve[i].src_offset; 490 te->output_format = mgr->ve->native_format[i]; 491 te->output_offset = k->output_stride; 492 493 k->output_stride += mgr->ve->native_format_size[i]; 494 k->nr_elements++; 495 } 496 497 /* Translate buffers. */ 498 for (type = 0; type < VB_NUM; type++) { 499 if (key[type].nr_elements) { 500 u_vbuf_translate_buffers(mgr, &key[type], mask[type], 501 mgr->fallback_vbs[type], 502 start[type], num[type], 503 start_index, num_indices, min_index, 504 unroll_indices && type == VB_VERTEX); 505 506 /* Fixup the stride for constant attribs. */ 507 if (type == VB_CONST) { 508 mgr->real_vertex_buffer[mgr->fallback_vbs[VB_CONST]].stride = 0; 509 } 510 } 511 } 512 513 /* Setup new vertex elements. */ 514 for (i = 0; i < mgr->ve->count; i++) { 515 for (type = 0; type < VB_NUM; type++) { 516 if (elem_index[type][i] < key[type].nr_elements) { 517 struct translate_element *te = &key[type].element[elem_index[type][i]]; 518 mgr->fallback_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor; 519 mgr->fallback_velems[i].src_format = te->output_format; 520 mgr->fallback_velems[i].src_offset = te->output_offset; 521 mgr->fallback_velems[i].vertex_buffer_index = mgr->fallback_vbs[type]; 522 523 /* elem_index[type][i] can only be set for one type. */ 524 assert(type > VB_INSTANCE || elem_index[type+1][i] == ~0); 525 assert(type > VB_VERTEX || elem_index[type+2][i] == ~0); 526 break; 527 } 528 } 529 /* No translating, just copy the original vertex element over. */ 530 if (type == VB_NUM) { 531 memcpy(&mgr->fallback_velems[i], &mgr->ve->ve[i], 532 sizeof(struct pipe_vertex_element)); 533 } 534 } 535 536 mgr->fallback_ve = u_vbuf_cache_set_vertex_elements(mgr, mgr->ve->count, 537 mgr->fallback_velems); 538 return TRUE; 539} 540 541static void u_vbuf_translate_end(struct u_vbuf_priv *mgr) 542{ 543 unsigned i; 544 545 /* Restore vertex elements. */ 546 mgr->driver_bind_vertex_elements_state(mgr->pipe, mgr->ve->driver_cso); 547 mgr->fallback_ve = NULL; 548 549 /* Unreference the now-unused VBOs. */ 550 for (i = 0; i < VB_NUM; i++) { 551 unsigned vb = mgr->fallback_vbs[i]; 552 if (vb != ~0) { 553 pipe_resource_reference(&mgr->real_vertex_buffer[vb].buffer, NULL); 554 mgr->fallback_vbs[i] = ~0; 555 } 556 } 557 mgr->nr_real_vertex_buffers = mgr->b.nr_vertex_buffers; 558} 559 560#define FORMAT_REPLACE(what, withwhat) \ 561 case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break 562 563static void * 564u_vbuf_create_vertex_elements(struct pipe_context *pipe, 565 unsigned count, 566 const struct pipe_vertex_element *attribs) 567{ 568 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw; 569 unsigned i; 570 struct pipe_vertex_element native_attribs[PIPE_MAX_ATTRIBS]; 571 struct u_vbuf_elements *ve = CALLOC_STRUCT(u_vbuf_elements); 572 573 ve->count = count; 574 575 memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count); 576 memcpy(native_attribs, attribs, sizeof(struct pipe_vertex_element) * count); 577 578 /* Set the best native format in case the original format is not 579 * supported. */ 580 for (i = 0; i < count; i++) { 581 enum pipe_format format = ve->ve[i].src_format; 582 583 ve->src_format_size[i] = util_format_get_blocksize(format); 584 585 /* Choose a native format. 586 * For now we don't care about the alignment, that's going to 587 * be sorted out later. */ 588 if (!mgr->b.caps.format_fixed32) { 589 switch (format) { 590 FORMAT_REPLACE(R32_FIXED, R32_FLOAT); 591 FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT); 592 FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT); 593 FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT); 594 default:; 595 } 596 } 597 if (!mgr->b.caps.format_float16) { 598 switch (format) { 599 FORMAT_REPLACE(R16_FLOAT, R32_FLOAT); 600 FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT); 601 FORMAT_REPLACE(R16G16B16_FLOAT, R32G32B32_FLOAT); 602 FORMAT_REPLACE(R16G16B16A16_FLOAT, R32G32B32A32_FLOAT); 603 default:; 604 } 605 } 606 if (!mgr->b.caps.format_float64) { 607 switch (format) { 608 FORMAT_REPLACE(R64_FLOAT, R32_FLOAT); 609 FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT); 610 FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT); 611 FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT); 612 default:; 613 } 614 } 615 if (!mgr->b.caps.format_norm32) { 616 switch (format) { 617 FORMAT_REPLACE(R32_UNORM, R32_FLOAT); 618 FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT); 619 FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT); 620 FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT); 621 FORMAT_REPLACE(R32_SNORM, R32_FLOAT); 622 FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT); 623 FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT); 624 FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT); 625 default:; 626 } 627 } 628 if (!mgr->b.caps.format_scaled32) { 629 switch (format) { 630 FORMAT_REPLACE(R32_USCALED, R32_FLOAT); 631 FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT); 632 FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT); 633 FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT); 634 FORMAT_REPLACE(R32_SSCALED, R32_FLOAT); 635 FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT); 636 FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT); 637 FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT); 638 default:; 639 } 640 } 641 642 native_attribs[i].src_format = format; 643 ve->native_format[i] = format; 644 ve->native_format_size[i] = 645 util_format_get_blocksize(ve->native_format[i]); 646 647 ve->incompatible_layout_elem[i] = 648 ve->ve[i].src_format != ve->native_format[i] || 649 (!mgr->b.caps.fetch_dword_unaligned && ve->ve[i].src_offset % 4 != 0); 650 ve->incompatible_layout = 651 ve->incompatible_layout || 652 ve->incompatible_layout_elem[i]; 653 } 654 655 /* Align the formats to the size of DWORD if needed. */ 656 if (!mgr->b.caps.fetch_dword_unaligned) { 657 for (i = 0; i < count; i++) { 658 ve->native_format_size[i] = align(ve->native_format_size[i], 4); 659 } 660 } 661 662 ve->driver_cso = 663 mgr->driver_create_vertex_elements_state(pipe, count, native_attribs); 664 return ve; 665} 666 667static void u_vbuf_bind_vertex_elements(struct pipe_context *pipe, 668 void *cso) 669{ 670 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw; 671 struct u_vbuf_elements *ve = cso; 672 673 mgr->ve = ve; 674 mgr->b.vertex_elements = ve; 675 mgr->driver_bind_vertex_elements_state(pipe, ve ? ve->driver_cso : NULL); 676} 677 678static void u_vbuf_delete_vertex_elements(struct pipe_context *pipe, 679 void *cso) 680{ 681 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw; 682 struct u_vbuf_elements *ve = cso; 683 684 mgr->driver_delete_vertex_elements_state(pipe, ve->driver_cso); 685 FREE(ve); 686} 687 688static void u_vbuf_set_vertex_buffers(struct pipe_context *pipe, 689 unsigned count, 690 const struct pipe_vertex_buffer *bufs) 691{ 692 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)pipe->draw; 693 unsigned i; 694 695 mgr->any_user_vbs = FALSE; 696 mgr->incompatible_vb_layout = FALSE; 697 memset(mgr->incompatible_vb, 0, sizeof(mgr->incompatible_vb)); 698 699 if (!mgr->b.caps.fetch_dword_unaligned) { 700 /* Check if the strides and offsets are aligned to the size of DWORD. */ 701 for (i = 0; i < count; i++) { 702 if (bufs[i].buffer) { 703 if (bufs[i].stride % 4 != 0 || 704 bufs[i].buffer_offset % 4 != 0) { 705 mgr->incompatible_vb_layout = TRUE; 706 mgr->incompatible_vb[i] = TRUE; 707 } 708 } 709 } 710 } 711 712 for (i = 0; i < count; i++) { 713 const struct pipe_vertex_buffer *vb = &bufs[i]; 714 715 pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, vb->buffer); 716 717 mgr->real_vertex_buffer[i].buffer_offset = 718 mgr->b.vertex_buffer[i].buffer_offset = vb->buffer_offset; 719 720 mgr->real_vertex_buffer[i].stride = 721 mgr->b.vertex_buffer[i].stride = vb->stride; 722 723 if (!vb->buffer || 724 mgr->incompatible_vb[i]) { 725 pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL); 726 continue; 727 } 728 729 if (u_vbuf_resource(vb->buffer)->user_ptr) { 730 pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL); 731 mgr->any_user_vbs = TRUE; 732 continue; 733 } 734 735 pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, vb->buffer); 736 } 737 738 for (i = count; i < mgr->b.nr_vertex_buffers; i++) { 739 pipe_resource_reference(&mgr->b.vertex_buffer[i].buffer, NULL); 740 } 741 for (i = count; i < mgr->nr_real_vertex_buffers; i++) { 742 pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL); 743 } 744 745 mgr->b.nr_vertex_buffers = count; 746 mgr->nr_real_vertex_buffers = count; 747 748 if (!mgr->any_user_vbs && !mgr->incompatible_vb_layout) { 749 mgr->driver_set_vertex_buffers(pipe, mgr->nr_real_vertex_buffers, 750 mgr->real_vertex_buffer); 751 } 752} 753 754static void u_vbuf_set_index_buffer(struct pipe_context *pipe, 755 const struct pipe_index_buffer *ib) 756{ 757 struct u_vbuf_priv *mgr = pipe->draw; 758 759 if (ib && ib->buffer) { 760 assert(ib->offset % ib->index_size == 0); 761 pipe_resource_reference(&mgr->index_buffer.buffer, ib->buffer); 762 mgr->index_buffer.offset = ib->offset; 763 mgr->index_buffer.index_size = ib->index_size; 764 } else { 765 pipe_resource_reference(&mgr->index_buffer.buffer, NULL); 766 } 767 768 mgr->driver_set_index_buffer(pipe, ib); 769} 770 771static void 772u_vbuf_upload_buffers(struct u_vbuf_priv *mgr, 773 int start_vertex, unsigned num_vertices, 774 int start_instance, unsigned num_instances) 775{ 776 unsigned i; 777 unsigned nr_velems = mgr->ve->count; 778 unsigned nr_vbufs = mgr->b.nr_vertex_buffers; 779 struct pipe_vertex_element *velems = 780 mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve; 781 unsigned start_offset[PIPE_MAX_ATTRIBS]; 782 unsigned end_offset[PIPE_MAX_ATTRIBS] = {0}; 783 784 /* Determine how much data needs to be uploaded. */ 785 for (i = 0; i < nr_velems; i++) { 786 struct pipe_vertex_element *velem = &velems[i]; 787 unsigned index = velem->vertex_buffer_index; 788 struct pipe_vertex_buffer *vb = &mgr->b.vertex_buffer[index]; 789 unsigned instance_div, first, size; 790 791 /* Skip the buffers generated by translate. */ 792 if (index == mgr->fallback_vbs[VB_VERTEX] || 793 index == mgr->fallback_vbs[VB_INSTANCE] || 794 index == mgr->fallback_vbs[VB_CONST]) { 795 continue; 796 } 797 798 assert(vb->buffer); 799 800 if (!u_vbuf_resource(vb->buffer)->user_ptr) { 801 continue; 802 } 803 804 instance_div = velem->instance_divisor; 805 first = vb->buffer_offset + velem->src_offset; 806 807 if (!vb->stride) { 808 /* Constant attrib. */ 809 size = mgr->ve->src_format_size[i]; 810 } else if (instance_div) { 811 /* Per-instance attrib. */ 812 unsigned count = (num_instances + instance_div - 1) / instance_div; 813 first += vb->stride * start_instance; 814 size = vb->stride * (count - 1) + mgr->ve->src_format_size[i]; 815 } else { 816 /* Per-vertex attrib. */ 817 first += vb->stride * start_vertex; 818 size = vb->stride * (num_vertices - 1) + mgr->ve->src_format_size[i]; 819 } 820 821 /* Update offsets. */ 822 if (!end_offset[index]) { 823 start_offset[index] = first; 824 end_offset[index] = first + size; 825 } else { 826 if (first < start_offset[index]) 827 start_offset[index] = first; 828 if (first + size > end_offset[index]) 829 end_offset[index] = first + size; 830 } 831 } 832 833 /* Upload buffers. */ 834 for (i = 0; i < nr_vbufs; i++) { 835 unsigned start, end = end_offset[i]; 836 struct pipe_vertex_buffer *real_vb; 837 uint8_t *ptr; 838 839 if (!end) { 840 continue; 841 } 842 843 start = start_offset[i]; 844 assert(start < end); 845 846 real_vb = &mgr->real_vertex_buffer[i]; 847 ptr = u_vbuf_resource(mgr->b.vertex_buffer[i].buffer)->user_ptr; 848 849 u_upload_data(mgr->b.uploader, start, end - start, ptr + start, 850 &real_vb->buffer_offset, &real_vb->buffer); 851 852 real_vb->buffer_offset -= start; 853 } 854} 855 856unsigned u_vbuf_draw_max_vertex_count(struct u_vbuf *mgrb) 857{ 858 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; 859 unsigned i, nr = mgr->ve->count; 860 struct pipe_vertex_element *velems = 861 mgr->fallback_ve ? mgr->fallback_velems : mgr->ve->ve; 862 unsigned result = ~0; 863 864 for (i = 0; i < nr; i++) { 865 struct pipe_vertex_buffer *vb = 866 &mgr->real_vertex_buffer[velems[i].vertex_buffer_index]; 867 unsigned size, max_count, value; 868 869 /* We're not interested in constant and per-instance attribs. */ 870 if (!vb->buffer || 871 !vb->stride || 872 velems[i].instance_divisor) { 873 continue; 874 } 875 876 size = vb->buffer->width0; 877 878 /* Subtract buffer_offset. */ 879 value = vb->buffer_offset; 880 if (value >= size) { 881 return 0; 882 } 883 size -= value; 884 885 /* Subtract src_offset. */ 886 value = velems[i].src_offset; 887 if (value >= size) { 888 return 0; 889 } 890 size -= value; 891 892 /* Subtract format_size. */ 893 value = mgr->ve->native_format_size[i]; 894 if (value >= size) { 895 return 0; 896 } 897 size -= value; 898 899 /* Compute the max count. */ 900 max_count = 1 + size / vb->stride; 901 result = MIN2(result, max_count); 902 } 903 return result; 904} 905 906static boolean u_vbuf_need_minmax_index(struct u_vbuf_priv *mgr) 907{ 908 unsigned i, nr = mgr->ve->count; 909 910 for (i = 0; i < nr; i++) { 911 struct pipe_vertex_buffer *vb; 912 unsigned index; 913 914 /* Per-instance attribs don't need min/max_index. */ 915 if (mgr->ve->ve[i].instance_divisor) { 916 continue; 917 } 918 919 index = mgr->ve->ve[i].vertex_buffer_index; 920 vb = &mgr->b.vertex_buffer[index]; 921 922 /* Constant attribs don't need min/max_index. */ 923 if (!vb->stride) { 924 continue; 925 } 926 927 /* Per-vertex attribs need min/max_index. */ 928 if (u_vbuf_resource(vb->buffer)->user_ptr || 929 mgr->ve->incompatible_layout_elem[i] || 930 mgr->incompatible_vb[index]) { 931 return TRUE; 932 } 933 } 934 935 return FALSE; 936} 937 938static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf_priv *mgr) 939{ 940 unsigned i, nr = mgr->ve->count; 941 942 for (i = 0; i < nr; i++) { 943 struct pipe_vertex_buffer *vb; 944 unsigned index; 945 946 /* Per-instance attribs are not per-vertex data. */ 947 if (mgr->ve->ve[i].instance_divisor) { 948 continue; 949 } 950 951 index = mgr->ve->ve[i].vertex_buffer_index; 952 vb = &mgr->b.vertex_buffer[index]; 953 954 /* Constant attribs are not per-vertex data. */ 955 if (!vb->stride) { 956 continue; 957 } 958 959 /* Return true for the hw buffers which don't need to be translated. */ 960 /* XXX we could use some kind of a is-busy query. */ 961 if (!u_vbuf_resource(vb->buffer)->user_ptr && 962 !mgr->ve->incompatible_layout_elem[i] && 963 !mgr->incompatible_vb[index]) { 964 return TRUE; 965 } 966 } 967 968 return FALSE; 969} 970 971static void u_vbuf_get_minmax_index(struct pipe_context *pipe, 972 struct pipe_index_buffer *ib, 973 const struct pipe_draw_info *info, 974 int *out_min_index, 975 int *out_max_index) 976{ 977 struct pipe_transfer *transfer = NULL; 978 const void *indices; 979 unsigned i; 980 unsigned restart_index = info->restart_index; 981 982 if (u_vbuf_resource(ib->buffer)->user_ptr) { 983 indices = u_vbuf_resource(ib->buffer)->user_ptr + 984 ib->offset + info->start * ib->index_size; 985 } else { 986 indices = pipe_buffer_map_range(pipe, ib->buffer, 987 ib->offset + info->start * ib->index_size, 988 info->count * ib->index_size, 989 PIPE_TRANSFER_READ, &transfer); 990 } 991 992 switch (ib->index_size) { 993 case 4: { 994 const unsigned *ui_indices = (const unsigned*)indices; 995 unsigned max_ui = 0; 996 unsigned min_ui = ~0U; 997 if (info->primitive_restart) { 998 for (i = 0; i < info->count; i++) { 999 if (ui_indices[i] != restart_index) { 1000 if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; 1001 if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; 1002 } 1003 } 1004 } 1005 else { 1006 for (i = 0; i < info->count; i++) { 1007 if (ui_indices[i] > max_ui) max_ui = ui_indices[i]; 1008 if (ui_indices[i] < min_ui) min_ui = ui_indices[i]; 1009 } 1010 } 1011 *out_min_index = min_ui; 1012 *out_max_index = max_ui; 1013 break; 1014 } 1015 case 2: { 1016 const unsigned short *us_indices = (const unsigned short*)indices; 1017 unsigned max_us = 0; 1018 unsigned min_us = ~0U; 1019 if (info->primitive_restart) { 1020 for (i = 0; i < info->count; i++) { 1021 if (us_indices[i] != restart_index) { 1022 if (us_indices[i] > max_us) max_us = us_indices[i]; 1023 if (us_indices[i] < min_us) min_us = us_indices[i]; 1024 } 1025 } 1026 } 1027 else { 1028 for (i = 0; i < info->count; i++) { 1029 if (us_indices[i] > max_us) max_us = us_indices[i]; 1030 if (us_indices[i] < min_us) min_us = us_indices[i]; 1031 } 1032 } 1033 *out_min_index = min_us; 1034 *out_max_index = max_us; 1035 break; 1036 } 1037 case 1: { 1038 const unsigned char *ub_indices = (const unsigned char*)indices; 1039 unsigned max_ub = 0; 1040 unsigned min_ub = ~0U; 1041 if (info->primitive_restart) { 1042 for (i = 0; i < info->count; i++) { 1043 if (ub_indices[i] != restart_index) { 1044 if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; 1045 if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; 1046 } 1047 } 1048 } 1049 else { 1050 for (i = 0; i < info->count; i++) { 1051 if (ub_indices[i] > max_ub) max_ub = ub_indices[i]; 1052 if (ub_indices[i] < min_ub) min_ub = ub_indices[i]; 1053 } 1054 } 1055 *out_min_index = min_ub; 1056 *out_max_index = max_ub; 1057 break; 1058 } 1059 default: 1060 assert(0); 1061 *out_min_index = 0; 1062 *out_max_index = 0; 1063 } 1064 1065 if (transfer) { 1066 pipe_buffer_unmap(pipe, transfer); 1067 } 1068} 1069 1070void u_vbuf_draw_begin(struct u_vbuf *mgrb, 1071 struct pipe_draw_info *info) 1072{ 1073 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; 1074 int start_vertex, min_index; 1075 unsigned num_vertices; 1076 bool unroll_indices = false; 1077 1078 if (!mgr->incompatible_vb_layout && 1079 !mgr->ve->incompatible_layout && 1080 !mgr->any_user_vbs) { 1081 return; 1082 } 1083 1084 if (info->indexed) { 1085 int max_index; 1086 bool index_bounds_valid = false; 1087 1088 if (info->max_index != ~0) { 1089 min_index = info->min_index; 1090 max_index = info->max_index; 1091 index_bounds_valid = true; 1092 } else if (u_vbuf_need_minmax_index(mgr)) { 1093 u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, info, 1094 &min_index, &max_index); 1095 index_bounds_valid = true; 1096 } 1097 1098 /* If the index bounds are valid, it means some upload or translation 1099 * of per-vertex attribs will be performed. */ 1100 if (index_bounds_valid) { 1101 assert(min_index <= max_index); 1102 1103 start_vertex = min_index + info->index_bias; 1104 num_vertices = max_index + 1 - min_index; 1105 1106 /* Primitive restart doesn't work when unrolling indices. 1107 * We would have to break this drawing operation into several ones. */ 1108 /* Use some heuristic to see if unrolling indices improves 1109 * performance. */ 1110 if (!info->primitive_restart && 1111 num_vertices > info->count*2 && 1112 num_vertices-info->count > 32 && 1113 !u_vbuf_mapping_vertex_buffer_blocks(mgr)) { 1114 /*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/ 1115 unroll_indices = true; 1116 } 1117 } else { 1118 /* Nothing to do for per-vertex attribs. */ 1119 start_vertex = 0; 1120 num_vertices = 0; 1121 min_index = 0; 1122 } 1123 } else { 1124 start_vertex = info->start; 1125 num_vertices = info->count; 1126 min_index = 0; 1127 } 1128 1129 /* Translate vertices with non-native layouts or formats. */ 1130 if (unroll_indices || 1131 mgr->incompatible_vb_layout || 1132 mgr->ve->incompatible_layout) { 1133 /* XXX check the return value */ 1134 u_vbuf_translate_begin(mgr, start_vertex, num_vertices, 1135 info->start_instance, info->instance_count, 1136 info->start, info->count, min_index, 1137 unroll_indices); 1138 } 1139 1140 /* Upload user buffers. */ 1141 if (mgr->any_user_vbs) { 1142 u_vbuf_upload_buffers(mgr, start_vertex, num_vertices, 1143 info->start_instance, info->instance_count); 1144 } 1145 1146 /* 1147 if (unroll_indices) { 1148 printf("unrolling indices: start_vertex = %i, num_vertices = %i\n", 1149 start_vertex, num_vertices); 1150 util_dump_draw_info(stdout, info); 1151 printf("\n"); 1152 } 1153 1154 unsigned i; 1155 for (i = 0; i < mgr->b.nr_vertex_buffers; i++) { 1156 printf("input %i: ", i); 1157 util_dump_vertex_buffer(stdout, mgr->b.vertex_buffer+i); 1158 printf("\n"); 1159 } 1160 for (i = 0; i < mgr->nr_real_vertex_buffers; i++) { 1161 printf("real %i: ", i); 1162 util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i); 1163 printf("\n"); 1164 } 1165 */ 1166 1167 if (unroll_indices) { 1168 info->indexed = FALSE; 1169 info->index_bias = 0; 1170 info->min_index = 0; 1171 info->max_index = info->count - 1; 1172 info->start = 0; 1173 } 1174 1175 mgr->driver_set_vertex_buffers(mgr->pipe, mgr->nr_real_vertex_buffers, 1176 mgr->real_vertex_buffer); 1177} 1178 1179void u_vbuf_draw_end(struct u_vbuf *mgrb) 1180{ 1181 struct u_vbuf_priv *mgr = (struct u_vbuf_priv*)mgrb; 1182 1183 if (mgr->fallback_ve) { 1184 u_vbuf_translate_end(mgr); 1185 } 1186} 1187 1188static void u_vbuf_install(struct u_vbuf_priv *mgr) 1189{ 1190 struct pipe_context *pipe = mgr->pipe; 1191 assert(!pipe->draw); 1192 1193 pipe->draw = mgr; 1194 mgr->driver_set_index_buffer = pipe->set_index_buffer; 1195 mgr->driver_set_vertex_buffers = pipe->set_vertex_buffers; 1196 mgr->driver_create_vertex_elements_state = 1197 pipe->create_vertex_elements_state; 1198 mgr->driver_bind_vertex_elements_state = pipe->bind_vertex_elements_state; 1199 mgr->driver_delete_vertex_elements_state = 1200 pipe->delete_vertex_elements_state; 1201 pipe->set_index_buffer = u_vbuf_set_index_buffer; 1202 pipe->set_vertex_buffers = u_vbuf_set_vertex_buffers; 1203 pipe->create_vertex_elements_state = u_vbuf_create_vertex_elements; 1204 pipe->bind_vertex_elements_state = u_vbuf_bind_vertex_elements; 1205 pipe->delete_vertex_elements_state = u_vbuf_delete_vertex_elements; 1206} 1207