1 /************************************************************************** 2 * 3 * Copyright 2010 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 TUNGSTEN GRAPHICS 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 "draw/draw_context.h" 31 #include "draw/draw_gs.h" 32 #include "draw/draw_vbuf.h" 33 #include "draw/draw_vertex.h" 34 #include "draw/draw_pt.h" 35 #include "draw/draw_vs.h" 36 #include "draw/draw_llvm.h" 37 #include "gallivm/lp_bld_init.h" 38 39 40 struct llvm_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 50 unsigned vertex_data_offset; 51 unsigned vertex_size; 52 unsigned input_prim; 53 unsigned opt; 54 55 struct draw_llvm *llvm; 56 struct draw_llvm_variant *current_variant; 57 }; 58 59 60 static void 61 llvm_middle_end_prepare( struct draw_pt_middle_end *middle, 62 unsigned in_prim, 63 unsigned opt, 64 unsigned *max_vertices ) 65 { 66 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 67 struct draw_context *draw = fpme->draw; 68 struct llvm_vertex_shader *shader = 69 llvm_vertex_shader(draw->vs.vertex_shader); 70 char store[DRAW_LLVM_MAX_VARIANT_KEY_SIZE]; 71 struct draw_llvm_variant_key *key; 72 struct draw_llvm_variant *variant = NULL; 73 struct draw_llvm_variant_list_item *li; 74 const unsigned out_prim = (draw->gs.geometry_shader ? 75 draw->gs.geometry_shader->output_primitive : 76 in_prim); 77 78 /* Add one to num_outputs because the pipeline occasionally tags on 79 * an additional texcoord, eg for AA lines. 80 */ 81 const unsigned nr = MAX2( shader->base.info.num_inputs, 82 shader->base.info.num_outputs + 1 ); 83 84 fpme->input_prim = in_prim; 85 fpme->opt = opt; 86 87 /* Always leave room for the vertex header whether we need it or 88 * not. It's hard to get rid of it in particular because of the 89 * viewport code in draw_pt_post_vs.c. 90 */ 91 fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float); 92 93 94 /* XXX: it's not really gl rasterization rules we care about here, 95 * but gl vs dx9 clip spaces. 96 */ 97 draw_pt_post_vs_prepare( fpme->post_vs, 98 draw->clip_xy, 99 draw->clip_z, 100 draw->clip_user, 101 draw->guard_band_xy, 102 draw->identity_viewport, 103 (boolean)draw->rasterizer->gl_rasterization_rules, 104 (draw->vs.edgeflag_output ? TRUE : FALSE) ); 105 106 draw_pt_so_emit_prepare( fpme->so_emit ); 107 108 if (!(opt & PT_PIPELINE)) { 109 draw_pt_emit_prepare( fpme->emit, 110 out_prim, 111 max_vertices ); 112 113 *max_vertices = MAX2( *max_vertices, 4096 ); 114 } 115 else { 116 /* limit max fetches by limiting max_vertices */ 117 *max_vertices = 4096; 118 } 119 120 /* return even number */ 121 *max_vertices = *max_vertices & ~1; 122 123 key = draw_llvm_make_variant_key(fpme->llvm, store); 124 125 /* Search shader's list of variants for the key */ 126 li = first_elem(&shader->variants); 127 while (!at_end(&shader->variants, li)) { 128 if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) { 129 variant = li->base; 130 break; 131 } 132 li = next_elem(li); 133 } 134 135 if (variant) { 136 /* found the variant, move to head of global list (for LRU) */ 137 move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global); 138 } 139 else { 140 /* Need to create new variant */ 141 unsigned i; 142 143 /* First check if we've created too many variants. If so, free 144 * 25% of the LRU to avoid using too much memory. 145 */ 146 if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) { 147 /* 148 * XXX: should we flush here ? 149 */ 150 for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) { 151 struct draw_llvm_variant_list_item *item; 152 if (is_empty_list(&fpme->llvm->vs_variants_list)) { 153 break; 154 } 155 item = last_elem(&fpme->llvm->vs_variants_list); 156 assert(item); 157 assert(item->base); 158 draw_llvm_destroy_variant(item->base); 159 } 160 } 161 162 variant = draw_llvm_create_variant(fpme->llvm, nr, key); 163 164 if (variant) { 165 insert_at_head(&shader->variants, &variant->list_item_local); 166 insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global); 167 fpme->llvm->nr_variants++; 168 shader->variants_cached++; 169 } 170 } 171 172 fpme->current_variant = variant; 173 174 /*XXX we only support one constant buffer */ 175 fpme->llvm->jit_context.vs_constants = 176 draw->pt.user.vs_constants[0]; 177 fpme->llvm->jit_context.gs_constants = 178 draw->pt.user.gs_constants[0]; 179 fpme->llvm->jit_context.planes = 180 (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0]; 181 fpme->llvm->jit_context.viewport = 182 (float *)draw->viewport.scale; 183 184 } 185 186 187 static void pipeline(struct llvm_middle_end *llvm, 188 const struct draw_vertex_info *vert_info, 189 const struct draw_prim_info *prim_info) 190 { 191 if (prim_info->linear) 192 draw_pipeline_run_linear( llvm->draw, 193 vert_info, 194 prim_info); 195 else 196 draw_pipeline_run( llvm->draw, 197 vert_info, 198 prim_info ); 199 } 200 201 static void emit(struct pt_emit *emit, 202 const struct draw_vertex_info *vert_info, 203 const struct draw_prim_info *prim_info) 204 { 205 if (prim_info->linear) { 206 draw_pt_emit_linear(emit, vert_info, prim_info); 207 } 208 else { 209 draw_pt_emit(emit, vert_info, prim_info); 210 } 211 } 212 213 static void 214 llvm_pipeline_generic( struct draw_pt_middle_end *middle, 215 const struct draw_fetch_info *fetch_info, 216 const struct draw_prim_info *prim_info ) 217 { 218 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 219 struct draw_context *draw = fpme->draw; 220 struct draw_geometry_shader *gshader = draw->gs.geometry_shader; 221 struct draw_prim_info gs_prim_info; 222 struct draw_vertex_info llvm_vert_info; 223 struct draw_vertex_info gs_vert_info; 224 struct draw_vertex_info *vert_info; 225 unsigned opt = fpme->opt; 226 unsigned clipped = 0; 227 228 llvm_vert_info.count = fetch_info->count; 229 llvm_vert_info.vertex_size = fpme->vertex_size; 230 llvm_vert_info.stride = fpme->vertex_size; 231 llvm_vert_info.verts = 232 (struct vertex_header *)MALLOC(fpme->vertex_size * 233 align(fetch_info->count, lp_native_vector_width / 32)); 234 if (!llvm_vert_info.verts) { 235 assert(0); 236 return; 237 } 238 239 if (fetch_info->linear) 240 clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context, 241 llvm_vert_info.verts, 242 (const char **)draw->pt.user.vbuffer, 243 fetch_info->start, 244 fetch_info->count, 245 fpme->vertex_size, 246 draw->pt.vertex_buffer, 247 draw->instance_id); 248 else 249 clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context, 250 llvm_vert_info.verts, 251 (const char **)draw->pt.user.vbuffer, 252 fetch_info->elts, 253 fetch_info->count, 254 fpme->vertex_size, 255 draw->pt.vertex_buffer, 256 draw->instance_id); 257 258 /* Finished with fetch and vs: 259 */ 260 fetch_info = NULL; 261 vert_info = &llvm_vert_info; 262 263 264 if ((opt & PT_SHADE) && gshader) { 265 draw_geometry_shader_run(gshader, 266 draw->pt.user.gs_constants, 267 draw->pt.user.gs_constants_size, 268 vert_info, 269 prim_info, 270 &gs_vert_info, 271 &gs_prim_info); 272 273 FREE(vert_info->verts); 274 vert_info = &gs_vert_info; 275 prim_info = &gs_prim_info; 276 277 clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info ); 278 279 } 280 281 /* stream output needs to be done before clipping */ 282 draw_pt_so_emit( fpme->so_emit, 283 vert_info, 284 prim_info ); 285 286 if (clipped) { 287 opt |= PT_PIPELINE; 288 } 289 290 /* Do we need to run the pipeline? Now will come here if clipped 291 */ 292 if (opt & PT_PIPELINE) { 293 pipeline( fpme, 294 vert_info, 295 prim_info ); 296 } 297 else { 298 emit( fpme->emit, 299 vert_info, 300 prim_info ); 301 } 302 FREE(vert_info->verts); 303 } 304 305 306 static void llvm_middle_end_run( struct draw_pt_middle_end *middle, 307 const unsigned *fetch_elts, 308 unsigned fetch_count, 309 const ushort *draw_elts, 310 unsigned draw_count, 311 unsigned prim_flags ) 312 { 313 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 314 struct draw_fetch_info fetch_info; 315 struct draw_prim_info prim_info; 316 317 fetch_info.linear = FALSE; 318 fetch_info.start = 0; 319 fetch_info.elts = fetch_elts; 320 fetch_info.count = fetch_count; 321 322 prim_info.linear = FALSE; 323 prim_info.start = 0; 324 prim_info.count = draw_count; 325 prim_info.elts = draw_elts; 326 prim_info.prim = fpme->input_prim; 327 prim_info.flags = prim_flags; 328 prim_info.primitive_count = 1; 329 prim_info.primitive_lengths = &draw_count; 330 331 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 332 } 333 334 335 static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle, 336 unsigned start, 337 unsigned count, 338 unsigned prim_flags) 339 { 340 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 341 struct draw_fetch_info fetch_info; 342 struct draw_prim_info prim_info; 343 344 fetch_info.linear = TRUE; 345 fetch_info.start = start; 346 fetch_info.count = count; 347 fetch_info.elts = NULL; 348 349 prim_info.linear = TRUE; 350 prim_info.start = 0; 351 prim_info.count = count; 352 prim_info.elts = NULL; 353 prim_info.prim = fpme->input_prim; 354 prim_info.flags = prim_flags; 355 prim_info.primitive_count = 1; 356 prim_info.primitive_lengths = &count; 357 358 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 359 } 360 361 362 363 static boolean 364 llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle, 365 unsigned start, 366 unsigned count, 367 const ushort *draw_elts, 368 unsigned draw_count, 369 unsigned prim_flags ) 370 { 371 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 372 struct draw_fetch_info fetch_info; 373 struct draw_prim_info prim_info; 374 375 fetch_info.linear = TRUE; 376 fetch_info.start = start; 377 fetch_info.count = count; 378 fetch_info.elts = NULL; 379 380 prim_info.linear = FALSE; 381 prim_info.start = 0; 382 prim_info.count = draw_count; 383 prim_info.elts = draw_elts; 384 prim_info.prim = fpme->input_prim; 385 prim_info.flags = prim_flags; 386 prim_info.primitive_count = 1; 387 prim_info.primitive_lengths = &draw_count; 388 389 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 390 391 return TRUE; 392 } 393 394 395 396 static void llvm_middle_end_finish( struct draw_pt_middle_end *middle ) 397 { 398 /* nothing to do */ 399 } 400 401 static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle ) 402 { 403 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 404 405 if (fpme->fetch) 406 draw_pt_fetch_destroy( fpme->fetch ); 407 408 if (fpme->emit) 409 draw_pt_emit_destroy( fpme->emit ); 410 411 if (fpme->so_emit) 412 draw_pt_so_emit_destroy( fpme->so_emit ); 413 414 if (fpme->post_vs) 415 draw_pt_post_vs_destroy( fpme->post_vs ); 416 417 FREE(middle); 418 } 419 420 421 struct draw_pt_middle_end * 422 draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw) 423 { 424 struct llvm_middle_end *fpme = 0; 425 426 if (!draw->llvm) 427 return NULL; 428 429 fpme = CALLOC_STRUCT( llvm_middle_end ); 430 if (!fpme) 431 goto fail; 432 433 fpme->base.prepare = llvm_middle_end_prepare; 434 fpme->base.run = llvm_middle_end_run; 435 fpme->base.run_linear = llvm_middle_end_linear_run; 436 fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts; 437 fpme->base.finish = llvm_middle_end_finish; 438 fpme->base.destroy = llvm_middle_end_destroy; 439 440 fpme->draw = draw; 441 442 fpme->fetch = draw_pt_fetch_create( draw ); 443 if (!fpme->fetch) 444 goto fail; 445 446 fpme->post_vs = draw_pt_post_vs_create( draw ); 447 if (!fpme->post_vs) 448 goto fail; 449 450 fpme->emit = draw_pt_emit_create( draw ); 451 if (!fpme->emit) 452 goto fail; 453 454 fpme->so_emit = draw_pt_so_emit_create( draw ); 455 if (!fpme->so_emit) 456 goto fail; 457 458 fpme->llvm = draw->llvm; 459 if (!fpme->llvm) 460 goto fail; 461 462 fpme->current_variant = NULL; 463 464 return &fpme->base; 465 466 fail: 467 if (fpme) 468 llvm_middle_end_destroy( &fpme->base ); 469 470 return NULL; 471 } 472