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