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 #include "util/u_math.h" 29 #include "util/u_memory.h" 30 #include "util/u_prim.h" 31 #include "draw/draw_context.h" 32 #include "draw/draw_vbuf.h" 33 #include "draw/draw_vertex.h" 34 #include "draw/draw_prim_assembler.h" 35 #include "draw/draw_pt.h" 36 #include "draw/draw_vs.h" 37 #include "draw/draw_gs.h" 38 39 40 struct fetch_pipeline_middle_end { 41 struct draw_pt_middle_end base; 42 struct draw_context *draw; 43 44 struct pt_emit *emit; 45 struct pt_so_emit *so_emit; 46 struct pt_fetch *fetch; 47 struct pt_post_vs *post_vs; 48 49 unsigned vertex_data_offset; 50 unsigned vertex_size; 51 unsigned input_prim; 52 unsigned opt; 53 }; 54 55 56 /** cast wrapper */ 57 static inline struct fetch_pipeline_middle_end * 58 fetch_pipeline_middle_end(struct draw_pt_middle_end *middle) 59 { 60 return (struct fetch_pipeline_middle_end *) middle; 61 } 62 63 64 /** 65 * Prepare/validate middle part of the vertex pipeline. 66 * NOTE: if you change this function, also look at the LLVM 67 * function llvm_middle_end_prepare() for similar changes. 68 */ 69 static void 70 fetch_pipeline_prepare(struct draw_pt_middle_end *middle, 71 unsigned prim, 72 unsigned opt, 73 unsigned *max_vertices) 74 { 75 struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle); 76 struct draw_context *draw = fpme->draw; 77 struct draw_vertex_shader *vs = draw->vs.vertex_shader; 78 struct draw_geometry_shader *gs = draw->gs.geometry_shader; 79 unsigned i; 80 unsigned instance_id_index = ~0; 81 const unsigned gs_out_prim = (gs ? gs->output_primitive : 82 u_assembled_prim(prim)); 83 unsigned nr_vs_outputs = draw_total_vs_outputs(draw); 84 unsigned nr = MAX2(vs->info.num_inputs, nr_vs_outputs); 85 unsigned point_clip = draw->rasterizer->fill_front == PIPE_POLYGON_MODE_POINT || 86 gs_out_prim == PIPE_PRIM_POINTS; 87 88 if (gs) { 89 nr = MAX2(nr, gs->info.num_outputs + 1); 90 } 91 92 /* Scan for instanceID system value. 93 */ 94 for (i = 0; i < vs->info.num_inputs; i++) { 95 if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) { 96 instance_id_index = i; 97 break; 98 } 99 } 100 101 fpme->input_prim = prim; 102 fpme->opt = opt; 103 104 /* Always leave room for the vertex header whether we need it or 105 * not. It's hard to get rid of it in particular because of the 106 * viewport code in draw_pt_post_vs.c. 107 */ 108 fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float); 109 110 draw_pt_fetch_prepare( fpme->fetch, 111 vs->info.num_inputs, 112 fpme->vertex_size, 113 instance_id_index ); 114 draw_pt_post_vs_prepare( fpme->post_vs, 115 draw->clip_xy, 116 draw->clip_z, 117 draw->clip_user, 118 point_clip ? draw->guard_band_points_xy : 119 draw->guard_band_xy, 120 draw->bypass_viewport, 121 draw->rasterizer->clip_halfz, 122 (draw->vs.edgeflag_output ? TRUE : FALSE) ); 123 124 draw_pt_so_emit_prepare( fpme->so_emit, FALSE ); 125 126 if (!(opt & PT_PIPELINE)) { 127 draw_pt_emit_prepare( fpme->emit, 128 gs_out_prim, 129 max_vertices ); 130 131 *max_vertices = MAX2( *max_vertices, 4096 ); 132 } 133 else { 134 /* limit max fetches by limiting max_vertices */ 135 *max_vertices = 4096; 136 } 137 138 /* No need to prepare the shader. 139 */ 140 vs->prepare(vs, draw); 141 142 /* Make sure that the vertex size didn't change at any point above */ 143 assert(nr_vs_outputs == draw_total_vs_outputs(draw)); 144 } 145 146 147 static void 148 fetch_pipeline_bind_parameters(struct draw_pt_middle_end *middle) 149 { 150 /* No-op since the vertex shader executor and drawing pipeline 151 * just grab the constants, viewport, etc. from the draw context state. 152 */ 153 } 154 155 156 static void fetch( struct pt_fetch *fetch, 157 const struct draw_fetch_info *fetch_info, 158 char *output) 159 { 160 if (fetch_info->linear) { 161 draw_pt_fetch_run_linear( fetch, 162 fetch_info->start, 163 fetch_info->count, 164 output ); 165 } 166 else { 167 draw_pt_fetch_run( fetch, 168 fetch_info->elts, 169 fetch_info->count, 170 output ); 171 } 172 } 173 174 175 static void pipeline(struct fetch_pipeline_middle_end *fpme, 176 const struct draw_vertex_info *vert_info, 177 const struct draw_prim_info *prim_info) 178 { 179 if (prim_info->linear) 180 draw_pipeline_run_linear( fpme->draw, 181 vert_info, 182 prim_info); 183 else 184 draw_pipeline_run( fpme->draw, 185 vert_info, 186 prim_info ); 187 } 188 189 190 static void 191 emit(struct pt_emit *emit, 192 const struct draw_vertex_info *vert_info, 193 const struct draw_prim_info *prim_info) 194 { 195 if (prim_info->linear) { 196 draw_pt_emit_linear(emit, vert_info, prim_info); 197 } 198 else { 199 draw_pt_emit(emit, vert_info, prim_info); 200 } 201 } 202 203 204 static void 205 draw_vertex_shader_run(struct draw_vertex_shader *vshader, 206 const void *constants[PIPE_MAX_CONSTANT_BUFFERS], 207 unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS], 208 const struct draw_vertex_info *input_verts, 209 struct draw_vertex_info *output_verts) 210 { 211 output_verts->vertex_size = input_verts->vertex_size; 212 output_verts->stride = input_verts->vertex_size; 213 output_verts->count = input_verts->count; 214 output_verts->verts = 215 (struct vertex_header *)MALLOC(output_verts->vertex_size * 216 align(output_verts->count, 4)); 217 218 vshader->run_linear(vshader, 219 (const float (*)[4])input_verts->verts->data, 220 ( float (*)[4])output_verts->verts->data, 221 constants, 222 const_size, 223 input_verts->count, 224 input_verts->vertex_size, 225 input_verts->vertex_size); 226 } 227 228 229 static void 230 fetch_pipeline_generic(struct draw_pt_middle_end *middle, 231 const struct draw_fetch_info *fetch_info, 232 const struct draw_prim_info *in_prim_info) 233 { 234 struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle); 235 struct draw_context *draw = fpme->draw; 236 struct draw_vertex_shader *vshader = draw->vs.vertex_shader; 237 struct draw_geometry_shader *gshader = draw->gs.geometry_shader; 238 struct draw_prim_info gs_prim_info; 239 struct draw_vertex_info fetched_vert_info; 240 struct draw_vertex_info vs_vert_info; 241 struct draw_vertex_info gs_vert_info; 242 struct draw_vertex_info *vert_info; 243 struct draw_prim_info ia_prim_info; 244 struct draw_vertex_info ia_vert_info; 245 const struct draw_prim_info *prim_info = in_prim_info; 246 boolean free_prim_info = FALSE; 247 unsigned opt = fpme->opt; 248 249 fetched_vert_info.count = fetch_info->count; 250 fetched_vert_info.vertex_size = fpme->vertex_size; 251 fetched_vert_info.stride = fpme->vertex_size; 252 fetched_vert_info.verts = 253 (struct vertex_header *)MALLOC(fpme->vertex_size * 254 align(fetch_info->count, 4)); 255 if (!fetched_vert_info.verts) { 256 assert(0); 257 return; 258 } 259 if (draw->collect_statistics) { 260 draw->statistics.ia_vertices += prim_info->count; 261 draw->statistics.ia_primitives += 262 u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count); 263 draw->statistics.vs_invocations += fetch_info->count; 264 } 265 266 /* Fetch into our vertex buffer. 267 */ 268 fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts ); 269 270 /* Finished with fetch: 271 */ 272 fetch_info = NULL; 273 vert_info = &fetched_vert_info; 274 275 /* Run the shader, note that this overwrites the data[] parts of 276 * the pipeline verts. 277 */ 278 if (fpme->opt & PT_SHADE) { 279 draw_vertex_shader_run(vshader, 280 draw->pt.user.vs_constants, 281 draw->pt.user.vs_constants_size, 282 vert_info, 283 &vs_vert_info); 284 285 FREE(vert_info->verts); 286 vert_info = &vs_vert_info; 287 } 288 289 if ((fpme->opt & PT_SHADE) && gshader) { 290 draw_geometry_shader_run(gshader, 291 draw->pt.user.gs_constants, 292 draw->pt.user.gs_constants_size, 293 vert_info, 294 prim_info, 295 &vshader->info, 296 &gs_vert_info, 297 &gs_prim_info); 298 299 FREE(vert_info->verts); 300 vert_info = &gs_vert_info; 301 prim_info = &gs_prim_info; 302 } else { 303 if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) { 304 draw_prim_assembler_run(draw, prim_info, vert_info, 305 &ia_prim_info, &ia_vert_info); 306 307 if (ia_vert_info.count) { 308 FREE(vert_info->verts); 309 vert_info = &ia_vert_info; 310 prim_info = &ia_prim_info; 311 free_prim_info = TRUE; 312 } 313 } 314 } 315 if (prim_info->count == 0) { 316 debug_printf("GS/IA didn't emit any vertices!\n"); 317 318 FREE(vert_info->verts); 319 if (free_prim_info) { 320 FREE(prim_info->primitive_lengths); 321 } 322 return; 323 } 324 325 326 /* Stream output needs to be done before clipping. 327 * 328 * XXX: Stream output surely needs to respect the prim_info->elt 329 * lists. 330 */ 331 draw_pt_so_emit( fpme->so_emit, vert_info, prim_info ); 332 333 draw_stats_clipper_primitives(draw, prim_info); 334 335 /* 336 * if there's no position, need to stop now, or the latter stages 337 * will try to access non-existent position output. 338 */ 339 if (draw_current_shader_position_output(draw) != -1) { 340 341 if (draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info )) 342 { 343 opt |= PT_PIPELINE; 344 } 345 346 /* Do we need to run the pipeline? 347 */ 348 if (opt & PT_PIPELINE) { 349 pipeline( fpme, vert_info, prim_info ); 350 } 351 else { 352 emit( fpme->emit, vert_info, prim_info ); 353 } 354 } 355 FREE(vert_info->verts); 356 if (free_prim_info) { 357 FREE(prim_info->primitive_lengths); 358 } 359 } 360 361 362 static inline unsigned 363 prim_type(unsigned prim, unsigned flags) 364 { 365 if (flags & DRAW_LINE_LOOP_AS_STRIP) 366 return PIPE_PRIM_LINE_STRIP; 367 else 368 return prim; 369 } 370 371 372 static void 373 fetch_pipeline_run(struct draw_pt_middle_end *middle, 374 const unsigned *fetch_elts, 375 unsigned fetch_count, 376 const ushort *draw_elts, 377 unsigned draw_count, 378 unsigned prim_flags) 379 { 380 struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle); 381 struct draw_fetch_info fetch_info; 382 struct draw_prim_info prim_info; 383 384 fetch_info.linear = FALSE; 385 fetch_info.start = 0; 386 fetch_info.elts = fetch_elts; 387 fetch_info.count = fetch_count; 388 389 prim_info.linear = FALSE; 390 prim_info.start = 0; 391 prim_info.count = draw_count; 392 prim_info.elts = draw_elts; 393 prim_info.prim = prim_type(fpme->input_prim, prim_flags); 394 prim_info.flags = prim_flags; 395 prim_info.primitive_count = 1; 396 prim_info.primitive_lengths = &draw_count; 397 398 fetch_pipeline_generic( middle, &fetch_info, &prim_info ); 399 } 400 401 402 static void 403 fetch_pipeline_linear_run(struct draw_pt_middle_end *middle, 404 unsigned start, 405 unsigned count, 406 unsigned prim_flags) 407 { 408 struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle); 409 struct draw_fetch_info fetch_info; 410 struct draw_prim_info prim_info; 411 412 fetch_info.linear = TRUE; 413 fetch_info.start = start; 414 fetch_info.count = count; 415 fetch_info.elts = NULL; 416 417 prim_info.linear = TRUE; 418 prim_info.start = 0; 419 prim_info.count = count; 420 prim_info.elts = NULL; 421 prim_info.prim = prim_type(fpme->input_prim, prim_flags); 422 prim_info.flags = prim_flags; 423 prim_info.primitive_count = 1; 424 prim_info.primitive_lengths = &count; 425 426 fetch_pipeline_generic( middle, &fetch_info, &prim_info ); 427 } 428 429 430 431 static boolean 432 fetch_pipeline_linear_run_elts(struct draw_pt_middle_end *middle, 433 unsigned start, 434 unsigned count, 435 const ushort *draw_elts, 436 unsigned draw_count, 437 unsigned prim_flags ) 438 { 439 struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle); 440 struct draw_fetch_info fetch_info; 441 struct draw_prim_info prim_info; 442 443 fetch_info.linear = TRUE; 444 fetch_info.start = start; 445 fetch_info.count = count; 446 fetch_info.elts = NULL; 447 448 prim_info.linear = FALSE; 449 prim_info.start = 0; 450 prim_info.count = draw_count; 451 prim_info.elts = draw_elts; 452 prim_info.prim = prim_type(fpme->input_prim, prim_flags); 453 prim_info.flags = prim_flags; 454 prim_info.primitive_count = 1; 455 prim_info.primitive_lengths = &draw_count; 456 457 fetch_pipeline_generic( middle, &fetch_info, &prim_info ); 458 459 return TRUE; 460 } 461 462 463 static void 464 fetch_pipeline_finish( struct draw_pt_middle_end *middle ) 465 { 466 /* nothing to do */ 467 } 468 469 470 static void 471 fetch_pipeline_destroy( struct draw_pt_middle_end *middle ) 472 { 473 struct fetch_pipeline_middle_end *fpme = fetch_pipeline_middle_end(middle); 474 475 if (fpme->fetch) 476 draw_pt_fetch_destroy( fpme->fetch ); 477 478 if (fpme->emit) 479 draw_pt_emit_destroy( fpme->emit ); 480 481 if (fpme->so_emit) 482 draw_pt_so_emit_destroy( fpme->so_emit ); 483 484 if (fpme->post_vs) 485 draw_pt_post_vs_destroy( fpme->post_vs ); 486 487 FREE(middle); 488 } 489 490 491 struct draw_pt_middle_end * 492 draw_pt_fetch_pipeline_or_emit(struct draw_context *draw) 493 { 494 struct fetch_pipeline_middle_end *fpme = 495 CALLOC_STRUCT( fetch_pipeline_middle_end ); 496 if (!fpme) 497 goto fail; 498 499 fpme->base.prepare = fetch_pipeline_prepare; 500 fpme->base.bind_parameters = fetch_pipeline_bind_parameters; 501 fpme->base.run = fetch_pipeline_run; 502 fpme->base.run_linear = fetch_pipeline_linear_run; 503 fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts; 504 fpme->base.finish = fetch_pipeline_finish; 505 fpme->base.destroy = fetch_pipeline_destroy; 506 507 fpme->draw = draw; 508 509 fpme->fetch = draw_pt_fetch_create( draw ); 510 if (!fpme->fetch) 511 goto fail; 512 513 fpme->post_vs = draw_pt_post_vs_create( draw ); 514 if (!fpme->post_vs) 515 goto fail; 516 517 fpme->emit = draw_pt_emit_create( draw ); 518 if (!fpme->emit) 519 goto fail; 520 521 fpme->so_emit = draw_pt_so_emit_create( draw ); 522 if (!fpme->so_emit) 523 goto fail; 524 525 return &fpme->base; 526 527 fail: 528 if (fpme) 529 fetch_pipeline_destroy( &fpme->base ); 530 531 return NULL; 532 } 533