1 /************************************************************************** 2 * 3 * Copyright 2007 VMware, Inc. 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 VMWARE 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 /* 29 * Authors: 30 * Keith Whitwell <keithw (at) vmware.com> 31 */ 32 33 #include "draw/draw_context.h" 34 #include "draw/draw_gs.h" 35 #include "draw/draw_private.h" 36 #include "draw/draw_pt.h" 37 #include "draw/draw_vbuf.h" 38 #include "draw/draw_vs.h" 39 #include "tgsi/tgsi_dump.h" 40 #include "util/u_math.h" 41 #include "util/u_prim.h" 42 #include "util/u_format.h" 43 #include "util/u_draw.h" 44 45 46 DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE) 47 DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE) 48 49 /* Overall we split things into: 50 * - frontend -- prepare fetch_elts, draw_elts - eg vsplit 51 * - middle -- fetch, shade, cliptest, viewport 52 * - pipeline -- the prim pipeline: clipping, wide lines, etc 53 * - backend -- the vbuf_render provided by the driver. 54 */ 55 static boolean 56 draw_pt_arrays(struct draw_context *draw, 57 unsigned prim, 58 unsigned start, 59 unsigned count) 60 { 61 struct draw_pt_front_end *frontend = NULL; 62 struct draw_pt_middle_end *middle = NULL; 63 unsigned opt = 0; 64 65 /* Sanitize primitive length: 66 */ 67 { 68 unsigned first, incr; 69 draw_pt_split_prim(prim, &first, &incr); 70 count = draw_pt_trim_count(count, first, incr); 71 if (count < first) 72 return TRUE; 73 } 74 75 if (!draw->force_passthrough) { 76 unsigned gs_out_prim = (draw->gs.geometry_shader ? 77 draw->gs.geometry_shader->output_primitive : 78 prim); 79 80 if (!draw->render) { 81 opt |= PT_PIPELINE; 82 } 83 84 if (draw_need_pipeline(draw, 85 draw->rasterizer, 86 gs_out_prim)) { 87 opt |= PT_PIPELINE; 88 } 89 90 if ((draw->clip_xy || 91 draw->clip_z || 92 draw->clip_user) && !draw->pt.test_fse) { 93 opt |= PT_CLIPTEST; 94 } 95 96 opt |= PT_SHADE; 97 } 98 99 if (draw->pt.middle.llvm) { 100 middle = draw->pt.middle.llvm; 101 } else { 102 if (opt == 0) 103 middle = draw->pt.middle.fetch_emit; 104 else if (opt == PT_SHADE && !draw->pt.no_fse) 105 middle = draw->pt.middle.fetch_shade_emit; 106 else 107 middle = draw->pt.middle.general; 108 } 109 110 frontend = draw->pt.frontend; 111 112 if (frontend) { 113 if (draw->pt.prim != prim || draw->pt.opt != opt) { 114 /* In certain conditions switching primitives requires us to flush 115 * and validate the different stages. One example is when smooth 116 * lines are active but first drawn with triangles and then with 117 * lines. 118 */ 119 draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); 120 frontend = NULL; 121 } else if (draw->pt.eltSize != draw->pt.user.eltSize) { 122 /* Flush draw state if eltSize changed. 123 * This could be improved so only the frontend is flushed since it 124 * converts all indices to ushorts and the fetch part of the middle 125 * always prepares both linear and indexed. 126 */ 127 frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE ); 128 frontend = NULL; 129 } 130 } 131 132 if (!frontend) { 133 frontend = draw->pt.front.vsplit; 134 135 frontend->prepare( frontend, prim, middle, opt ); 136 137 draw->pt.frontend = frontend; 138 draw->pt.eltSize = draw->pt.user.eltSize; 139 draw->pt.prim = prim; 140 draw->pt.opt = opt; 141 } 142 143 if (draw->pt.rebind_parameters) { 144 /* update constants, viewport dims, clip planes, etc */ 145 middle->bind_parameters(middle); 146 draw->pt.rebind_parameters = FALSE; 147 } 148 149 frontend->run( frontend, start, count ); 150 151 return TRUE; 152 } 153 154 void draw_pt_flush( struct draw_context *draw, unsigned flags ) 155 { 156 assert(flags); 157 158 if (draw->pt.frontend) { 159 draw->pt.frontend->flush( draw->pt.frontend, flags ); 160 161 /* don't prepare if we only are flushing the backend */ 162 if (flags & DRAW_FLUSH_STATE_CHANGE) 163 draw->pt.frontend = NULL; 164 } 165 166 if (flags & DRAW_FLUSH_PARAMETER_CHANGE) { 167 draw->pt.rebind_parameters = TRUE; 168 } 169 } 170 171 172 173 boolean draw_pt_init( struct draw_context *draw ) 174 { 175 draw->pt.test_fse = debug_get_option_draw_fse(); 176 draw->pt.no_fse = debug_get_option_draw_no_fse(); 177 178 draw->pt.front.vsplit = draw_pt_vsplit(draw); 179 if (!draw->pt.front.vsplit) 180 return FALSE; 181 182 draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw ); 183 if (!draw->pt.middle.fetch_emit) 184 return FALSE; 185 186 draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw ); 187 if (!draw->pt.middle.fetch_shade_emit) 188 return FALSE; 189 190 draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw ); 191 if (!draw->pt.middle.general) 192 return FALSE; 193 194 #if HAVE_LLVM 195 if (draw->llvm) 196 draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw ); 197 #endif 198 199 return TRUE; 200 } 201 202 203 void draw_pt_destroy( struct draw_context *draw ) 204 { 205 if (draw->pt.middle.llvm) { 206 draw->pt.middle.llvm->destroy( draw->pt.middle.llvm ); 207 draw->pt.middle.llvm = NULL; 208 } 209 210 if (draw->pt.middle.general) { 211 draw->pt.middle.general->destroy( draw->pt.middle.general ); 212 draw->pt.middle.general = NULL; 213 } 214 215 if (draw->pt.middle.fetch_emit) { 216 draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit ); 217 draw->pt.middle.fetch_emit = NULL; 218 } 219 220 if (draw->pt.middle.fetch_shade_emit) { 221 draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit ); 222 draw->pt.middle.fetch_shade_emit = NULL; 223 } 224 225 if (draw->pt.front.vsplit) { 226 draw->pt.front.vsplit->destroy( draw->pt.front.vsplit ); 227 draw->pt.front.vsplit = NULL; 228 } 229 } 230 231 232 /** 233 * Debug- print the first 'count' vertices. 234 */ 235 static void 236 draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count) 237 { 238 uint i; 239 240 debug_printf("Draw arrays(prim = %u, start = %u, count = %u)\n", 241 prim, start, count); 242 243 for (i = 0; i < count; i++) { 244 uint ii = 0; 245 uint j; 246 247 if (draw->pt.user.eltSize) { 248 /* indexed arrays */ 249 250 switch (draw->pt.user.eltSize) { 251 case 1: 252 { 253 const ubyte *elem = (const ubyte *) draw->pt.user.elts; 254 ii = elem[start + i]; 255 } 256 break; 257 case 2: 258 { 259 const ushort *elem = (const ushort *) draw->pt.user.elts; 260 ii = elem[start + i]; 261 } 262 break; 263 case 4: 264 { 265 const uint *elem = (const uint *) draw->pt.user.elts; 266 ii = elem[start + i]; 267 } 268 break; 269 default: 270 assert(0); 271 return; 272 } 273 ii += draw->pt.user.eltBias; 274 debug_printf("Element[%u + %u] + %i -> Vertex %u:\n", start, i, 275 draw->pt.user.eltBias, ii); 276 } 277 else { 278 /* non-indexed arrays */ 279 ii = start + i; 280 debug_printf("Vertex %u:\n", ii); 281 } 282 283 for (j = 0; j < draw->pt.nr_vertex_elements; j++) { 284 uint buf = draw->pt.vertex_element[j].vertex_buffer_index; 285 ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf].map; 286 287 if (draw->pt.vertex_element[j].instance_divisor) { 288 ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor; 289 } 290 291 ptr += draw->pt.vertex_buffer[buf].buffer_offset; 292 ptr += draw->pt.vertex_buffer[buf].stride * ii; 293 ptr += draw->pt.vertex_element[j].src_offset; 294 295 debug_printf(" Attr %u: ", j); 296 switch (draw->pt.vertex_element[j].src_format) { 297 case PIPE_FORMAT_R32_FLOAT: 298 { 299 float *v = (float *) ptr; 300 debug_printf("R %f @ %p\n", v[0], (void *) v); 301 } 302 break; 303 case PIPE_FORMAT_R32G32_FLOAT: 304 { 305 float *v = (float *) ptr; 306 debug_printf("RG %f %f @ %p\n", v[0], v[1], (void *) v); 307 } 308 break; 309 case PIPE_FORMAT_R32G32B32_FLOAT: 310 { 311 float *v = (float *) ptr; 312 debug_printf("RGB %f %f %f @ %p\n", v[0], v[1], v[2], (void *) v); 313 } 314 break; 315 case PIPE_FORMAT_R32G32B32A32_FLOAT: 316 { 317 float *v = (float *) ptr; 318 debug_printf("RGBA %f %f %f %f @ %p\n", v[0], v[1], v[2], v[3], 319 (void *) v); 320 } 321 break; 322 case PIPE_FORMAT_B8G8R8A8_UNORM: 323 { 324 ubyte *u = (ubyte *) ptr; 325 debug_printf("BGRA %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3], 326 (void *) u); 327 } 328 break; 329 case PIPE_FORMAT_A8R8G8B8_UNORM: 330 { 331 ubyte *u = (ubyte *) ptr; 332 debug_printf("ARGB %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3], 333 (void *) u); 334 } 335 break; 336 default: 337 debug_printf("other format %s (fix me)\n", 338 util_format_name(draw->pt.vertex_element[j].src_format)); 339 } 340 } 341 } 342 } 343 344 345 /** Helper code for below */ 346 #define PRIM_RESTART_LOOP(elements) \ 347 do { \ 348 for (j = 0; j < count; j++) { \ 349 i = draw_overflow_uadd(start, j, MAX_LOOP_IDX); \ 350 if (i < elt_max && elements[i] == info->restart_index) { \ 351 if (cur_count > 0) { \ 352 /* draw elts up to prev pos */ \ 353 draw_pt_arrays(draw, prim, cur_start, cur_count); \ 354 } \ 355 /* begin new prim at next elt */ \ 356 cur_start = i + 1; \ 357 cur_count = 0; \ 358 } \ 359 else { \ 360 cur_count++; \ 361 } \ 362 } \ 363 if (cur_count > 0) { \ 364 draw_pt_arrays(draw, prim, cur_start, cur_count); \ 365 } \ 366 } while (0) 367 368 369 /** 370 * For drawing prims with primitive restart enabled. 371 * Scan for restart indexes and draw the runs of elements/vertices between 372 * the restarts. 373 */ 374 static void 375 draw_pt_arrays_restart(struct draw_context *draw, 376 const struct pipe_draw_info *info) 377 { 378 const unsigned prim = info->mode; 379 const unsigned start = info->start; 380 const unsigned count = info->count; 381 const unsigned elt_max = draw->pt.user.eltMax; 382 unsigned i, j, cur_start, cur_count; 383 /* The largest index within a loop using the i variable as the index. 384 * Used for overflow detection */ 385 const unsigned MAX_LOOP_IDX = 0xffffffff; 386 387 assert(info->primitive_restart); 388 389 if (draw->pt.user.eltSize) { 390 /* indexed prims (draw_elements) */ 391 cur_start = start; 392 cur_count = 0; 393 394 switch (draw->pt.user.eltSize) { 395 case 1: 396 { 397 const ubyte *elt_ub = (const ubyte *) draw->pt.user.elts; 398 PRIM_RESTART_LOOP(elt_ub); 399 } 400 break; 401 case 2: 402 { 403 const ushort *elt_us = (const ushort *) draw->pt.user.elts; 404 PRIM_RESTART_LOOP(elt_us); 405 } 406 break; 407 case 4: 408 { 409 const uint *elt_ui = (const uint *) draw->pt.user.elts; 410 PRIM_RESTART_LOOP(elt_ui); 411 } 412 break; 413 default: 414 assert(0 && "bad eltSize in draw_arrays()"); 415 } 416 } 417 else { 418 /* Non-indexed prims (draw_arrays). 419 * Primitive restart should have been handled in the state tracker. 420 */ 421 draw_pt_arrays(draw, prim, start, count); 422 } 423 } 424 425 426 /** 427 * Resolve true values within pipe_draw_info. 428 * If we're rendering from transform feedback/stream output 429 * buffers both the count and max_index need to be computed 430 * from the attached stream output target. 431 */ 432 static void 433 resolve_draw_info(const struct pipe_draw_info *raw_info, 434 struct pipe_draw_info *info, 435 struct pipe_vertex_buffer *vertex_buffer) 436 { 437 memcpy(info, raw_info, sizeof(struct pipe_draw_info)); 438 439 if (raw_info->count_from_stream_output) { 440 struct draw_so_target *target = 441 (struct draw_so_target *)info->count_from_stream_output; 442 assert(vertex_buffer != NULL); 443 info->count = target->internal_offset / vertex_buffer->stride; 444 445 /* Stream output draw can not be indexed */ 446 debug_assert(!info->indexed); 447 info->max_index = info->count - 1; 448 } 449 } 450 451 /** 452 * Draw vertex arrays. 453 * This is the main entrypoint into the drawing module. If drawing an indexed 454 * primitive, the draw_set_indexes() function should have already been called 455 * to specify the element/index buffer information. 456 */ 457 void 458 draw_vbo(struct draw_context *draw, 459 const struct pipe_draw_info *info) 460 { 461 unsigned instance; 462 unsigned index_limit; 463 unsigned count; 464 unsigned fpstate = util_fpstate_get(); 465 struct pipe_draw_info resolved_info; 466 467 /* Make sure that denorms are treated like zeros. This is 468 * the behavior required by D3D10. OpenGL doesn't care. 469 */ 470 util_fpstate_set_denorms_to_zero(fpstate); 471 472 resolve_draw_info(info, &resolved_info, &(draw->pt.vertex_buffer[0])); 473 info = &resolved_info; 474 475 assert(info->instance_count > 0); 476 if (info->indexed) 477 assert(draw->pt.user.elts); 478 479 count = info->count; 480 481 draw->pt.user.eltBias = info->index_bias; 482 draw->pt.user.min_index = info->min_index; 483 draw->pt.user.max_index = info->max_index; 484 draw->pt.user.eltSize = info->indexed ? draw->pt.user.eltSizeIB : 0; 485 486 if (0) 487 debug_printf("draw_vbo(mode=%u start=%u count=%u):\n", 488 info->mode, info->start, count); 489 490 if (0) 491 tgsi_dump(draw->vs.vertex_shader->state.tokens, 0); 492 493 if (0) { 494 unsigned int i; 495 debug_printf("Elements:\n"); 496 for (i = 0; i < draw->pt.nr_vertex_elements; i++) { 497 debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n", 498 i, 499 draw->pt.vertex_element[i].src_offset, 500 draw->pt.vertex_element[i].instance_divisor, 501 draw->pt.vertex_element[i].vertex_buffer_index, 502 util_format_name(draw->pt.vertex_element[i].src_format)); 503 } 504 debug_printf("Buffers:\n"); 505 for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { 506 debug_printf(" %u: stride=%u offset=%u size=%d ptr=%p\n", 507 i, 508 draw->pt.vertex_buffer[i].stride, 509 draw->pt.vertex_buffer[i].buffer_offset, 510 (int) draw->pt.user.vbuffer[i].size, 511 draw->pt.user.vbuffer[i].map); 512 } 513 } 514 515 if (0) 516 draw_print_arrays(draw, info->mode, info->start, MIN2(count, 20)); 517 518 index_limit = util_draw_max_index(draw->pt.vertex_buffer, 519 draw->pt.vertex_element, 520 draw->pt.nr_vertex_elements, 521 info); 522 #if HAVE_LLVM 523 if (!draw->llvm) 524 #endif 525 { 526 if (index_limit == 0) { 527 /* one of the buffers is too small to do any valid drawing */ 528 debug_warning("draw: VBO too small to draw anything\n"); 529 util_fpstate_set(fpstate); 530 return; 531 } 532 } 533 534 /* If we're collecting stats then make sure we start from scratch */ 535 if (draw->collect_statistics) { 536 memset(&draw->statistics, 0, sizeof(draw->statistics)); 537 } 538 539 draw->pt.max_index = index_limit - 1; 540 draw->start_index = info->start; 541 542 /* 543 * TODO: We could use draw->pt.max_index to further narrow 544 * the min_index/max_index hints given by the state tracker. 545 */ 546 547 for (instance = 0; instance < info->instance_count; instance++) { 548 unsigned instance_idx = instance + info->start_instance; 549 draw->start_instance = info->start_instance; 550 draw->instance_id = instance; 551 /* check for overflow */ 552 if (instance_idx < instance || 553 instance_idx < draw->start_instance) { 554 /* if we overflown just set the instance id to the max */ 555 draw->instance_id = 0xffffffff; 556 } 557 558 draw_new_instance(draw); 559 560 if (info->primitive_restart) { 561 draw_pt_arrays_restart(draw, info); 562 } 563 else { 564 draw_pt_arrays(draw, info->mode, info->start, count); 565 } 566 } 567 568 /* If requested emit the pipeline statistics for this run */ 569 if (draw->collect_statistics) { 570 draw->render->pipeline_statistics(draw->render, &draw->statistics); 571 } 572 util_fpstate_set(fpstate); 573 } 574