draw_pt_fetch_shade_pipeline_llvm.c revision bf2d2772a21748b6279c1fc3397ab75450aff74e
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 38 39struct llvm_middle_end { 40 struct draw_pt_middle_end base; 41 struct draw_context *draw; 42 43 struct pt_emit *emit; 44 struct pt_so_emit *so_emit; 45 struct pt_fetch *fetch; 46 struct pt_post_vs *post_vs; 47 48 49 unsigned vertex_data_offset; 50 unsigned vertex_size; 51 unsigned input_prim; 52 unsigned opt; 53 54 struct draw_llvm *llvm; 55 struct draw_llvm_variant *variants; 56 struct draw_llvm_variant *current_variant; 57 int nr_variants; 58}; 59 60 61static void 62llvm_middle_end_prepare( struct draw_pt_middle_end *middle, 63 unsigned in_prim, 64 unsigned opt, 65 unsigned *max_vertices ) 66{ 67 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 68 struct draw_context *draw = fpme->draw; 69 struct draw_vertex_shader *vs = draw->vs.vertex_shader; 70 struct draw_llvm_variant_key key; 71 struct draw_llvm_variant *variant = NULL; 72 unsigned i; 73 unsigned instance_id_index = ~0; 74 75 76 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 unsigned nr = MAX2( vs->info.num_inputs, 84 vs->info.num_outputs + 1 ); 85 86 /* Scan for instanceID system value. 87 */ 88 for (i = 0; i < vs->info.num_inputs; i++) { 89 if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) { 90 instance_id_index = i; 91 break; 92 } 93 } 94 95 fpme->input_prim = in_prim; 96 fpme->opt = opt; 97 98 /* Always leave room for the vertex header whether we need it or 99 * not. It's hard to get rid of it in particular because of the 100 * viewport code in draw_pt_post_vs.c. 101 */ 102 fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float); 103 104 105 /* XXX: it's not really gl rasterization rules we care about here, 106 * but gl vs dx9 clip spaces. 107 */ 108 draw_pt_post_vs_prepare( fpme->post_vs, 109 (boolean)draw->bypass_clipping, 110 (boolean)(draw->identity_viewport), 111 (boolean)draw->rasterizer->gl_rasterization_rules, 112 (draw->vs.edgeflag_output ? TRUE : FALSE) ); 113 114 draw_pt_so_emit_prepare( fpme->so_emit ); 115 116 if (!(opt & PT_PIPELINE)) { 117 draw_pt_emit_prepare( fpme->emit, 118 out_prim, 119 max_vertices ); 120 121 *max_vertices = MAX2( *max_vertices, 122 DRAW_PIPE_MAX_VERTICES ); 123 } 124 else { 125 *max_vertices = DRAW_PIPE_MAX_VERTICES; 126 } 127 128 /* return even number */ 129 *max_vertices = *max_vertices & ~1; 130 131 draw_llvm_make_variant_key(fpme->llvm, &key); 132 133 variant = fpme->variants; 134 while(variant) { 135 if(memcmp(&variant->key, &key, sizeof key) == 0) 136 break; 137 138 variant = variant->next; 139 } 140 141 if (!variant) { 142 variant = draw_llvm_prepare(fpme->llvm, nr); 143 variant->next = fpme->variants; 144 fpme->variants = variant; 145 ++fpme->nr_variants; 146 } 147 fpme->current_variant = variant; 148 149 /*XXX we only support one constant buffer */ 150 fpme->llvm->jit_context.vs_constants = 151 draw->pt.user.vs_constants[0]; 152 fpme->llvm->jit_context.gs_constants = 153 draw->pt.user.gs_constants[0]; 154} 155 156 157static void pipeline(struct llvm_middle_end *llvm, 158 const struct draw_vertex_info *vert_info, 159 const struct draw_prim_info *prim_info) 160{ 161 if (prim_info->linear) 162 draw_pipeline_run_linear( llvm->draw, 163 vert_info, 164 prim_info); 165 else 166 draw_pipeline_run( llvm->draw, 167 vert_info, 168 prim_info ); 169} 170 171static void emit(struct pt_emit *emit, 172 const struct draw_vertex_info *vert_info, 173 const struct draw_prim_info *prim_info) 174{ 175 if (prim_info->linear) { 176 draw_pt_emit_linear(emit, vert_info, prim_info); 177 } 178 else { 179 draw_pt_emit(emit, vert_info, prim_info); 180 } 181} 182 183static void 184llvm_pipeline_generic( struct draw_pt_middle_end *middle, 185 const struct draw_fetch_info *fetch_info, 186 const struct draw_prim_info *prim_info ) 187{ 188 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 189 struct draw_context *draw = fpme->draw; 190 struct draw_geometry_shader *gshader = draw->gs.geometry_shader; 191 struct draw_prim_info gs_prim_info; 192 struct draw_vertex_info llvm_vert_info; 193 struct draw_vertex_info gs_vert_info; 194 struct draw_vertex_info *vert_info; 195 unsigned opt = fpme->opt; 196 197 llvm_vert_info.count = fetch_info->count; 198 llvm_vert_info.vertex_size = fpme->vertex_size; 199 llvm_vert_info.stride = fpme->vertex_size; 200 llvm_vert_info.verts = 201 (struct vertex_header *)MALLOC(fpme->vertex_size * 202 align(fetch_info->count, 4)); 203 if (!llvm_vert_info.verts) { 204 assert(0); 205 return; 206 } 207 208 if (fetch_info->linear) 209 fpme->current_variant->jit_func( &fpme->llvm->jit_context, 210 llvm_vert_info.verts, 211 (const char **)draw->pt.user.vbuffer, 212 fetch_info->start, 213 fetch_info->count, 214 fpme->vertex_size, 215 draw->pt.vertex_buffer ); 216 else 217 fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context, 218 llvm_vert_info.verts, 219 (const char **)draw->pt.user.vbuffer, 220 fetch_info->elts, 221 fetch_info->count, 222 fpme->vertex_size, 223 draw->pt.vertex_buffer); 224 225 /* Finished with fetch and vs: 226 */ 227 fetch_info = NULL; 228 vert_info = &llvm_vert_info; 229 230 231 if ((opt & PT_SHADE) && gshader) { 232 draw_geometry_shader_run(gshader, 233 draw->pt.user.gs_constants, 234 vert_info, 235 prim_info, 236 &gs_vert_info, 237 &gs_prim_info); 238 239 FREE(vert_info->verts); 240 vert_info = &gs_vert_info; 241 prim_info = &gs_prim_info; 242 } 243 244 /* stream output needs to be done before clipping */ 245 draw_pt_so_emit( fpme->so_emit, 246 vert_info, 247 prim_info ); 248 249 if (draw_pt_post_vs_run( fpme->post_vs, vert_info )) { 250 opt |= PT_PIPELINE; 251 } 252 253 /* Do we need to run the pipeline? 254 */ 255 if (opt & PT_PIPELINE) { 256 pipeline( fpme, 257 vert_info, 258 prim_info ); 259 } 260 else { 261 emit( fpme->emit, 262 vert_info, 263 prim_info ); 264 } 265 FREE(vert_info->verts); 266} 267 268 269static void llvm_middle_end_run( struct draw_pt_middle_end *middle, 270 const unsigned *fetch_elts, 271 unsigned fetch_count, 272 const ushort *draw_elts, 273 unsigned draw_count ) 274{ 275 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 276 struct draw_fetch_info fetch_info; 277 struct draw_prim_info prim_info; 278 279 fetch_info.linear = FALSE; 280 fetch_info.start = 0; 281 fetch_info.elts = fetch_elts; 282 fetch_info.count = fetch_count; 283 284 prim_info.linear = FALSE; 285 prim_info.start = 0; 286 prim_info.count = draw_count; 287 prim_info.elts = draw_elts; 288 prim_info.prim = fpme->input_prim; 289 prim_info.primitive_count = 1; 290 prim_info.primitive_lengths = &draw_count; 291 292 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 293} 294 295 296static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle, 297 unsigned start, 298 unsigned count) 299{ 300 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 301 struct draw_fetch_info fetch_info; 302 struct draw_prim_info prim_info; 303 304 fetch_info.linear = TRUE; 305 fetch_info.start = start; 306 fetch_info.count = count; 307 fetch_info.elts = NULL; 308 309 prim_info.linear = TRUE; 310 prim_info.start = 0; 311 prim_info.count = count; 312 prim_info.elts = NULL; 313 prim_info.prim = fpme->input_prim; 314 prim_info.primitive_count = 1; 315 prim_info.primitive_lengths = &count; 316 317 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 318} 319 320 321 322static boolean 323llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle, 324 unsigned start, 325 unsigned count, 326 const ushort *draw_elts, 327 unsigned draw_count ) 328{ 329 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 330 struct draw_fetch_info fetch_info; 331 struct draw_prim_info prim_info; 332 333 fetch_info.linear = TRUE; 334 fetch_info.start = start; 335 fetch_info.count = count; 336 fetch_info.elts = NULL; 337 338 prim_info.linear = FALSE; 339 prim_info.start = 0; 340 prim_info.count = draw_count; 341 prim_info.elts = draw_elts; 342 prim_info.prim = fpme->input_prim; 343 prim_info.primitive_count = 1; 344 prim_info.primitive_lengths = &draw_count; 345 346 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 347 348 return TRUE; 349} 350 351 352 353static void llvm_middle_end_finish( struct draw_pt_middle_end *middle ) 354{ 355 /* nothing to do */ 356} 357 358static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle ) 359{ 360 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 361 struct draw_context *draw = fpme->draw; 362 struct draw_llvm_variant *variant = NULL; 363 364 variant = fpme->variants; 365 while(variant) { 366 struct draw_llvm_variant *next = variant->next; 367 368 if (variant->function_elts) { 369 if (variant->function_elts) 370 LLVMFreeMachineCodeForFunction(draw->engine, 371 variant->function_elts); 372 LLVMDeleteFunction(variant->function_elts); 373 } 374 375 if (variant->function) { 376 if (variant->function) 377 LLVMFreeMachineCodeForFunction(draw->engine, 378 variant->function); 379 LLVMDeleteFunction(variant->function); 380 } 381 382 FREE(variant); 383 384 variant = next; 385 } 386 if (fpme->fetch) 387 draw_pt_fetch_destroy( fpme->fetch ); 388 389 if (fpme->emit) 390 draw_pt_emit_destroy( fpme->emit ); 391 392 if (fpme->so_emit) 393 draw_pt_so_emit_destroy( fpme->so_emit ); 394 395 if (fpme->post_vs) 396 draw_pt_post_vs_destroy( fpme->post_vs ); 397 398 if (fpme->llvm) 399 draw_llvm_destroy( fpme->llvm ); 400 401 FREE(middle); 402} 403 404 405struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_context *draw ) 406{ 407 struct llvm_middle_end *fpme = 0; 408 409 if (!draw->engine) 410 return NULL; 411 412 fpme = CALLOC_STRUCT( llvm_middle_end ); 413 if (!fpme) 414 goto fail; 415 416 fpme->base.prepare = llvm_middle_end_prepare; 417 fpme->base.run = llvm_middle_end_run; 418 fpme->base.run_linear = llvm_middle_end_linear_run; 419 fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts; 420 fpme->base.finish = llvm_middle_end_finish; 421 fpme->base.destroy = llvm_middle_end_destroy; 422 423 fpme->draw = draw; 424 425 fpme->fetch = draw_pt_fetch_create( draw ); 426 if (!fpme->fetch) 427 goto fail; 428 429 fpme->post_vs = draw_pt_post_vs_create( draw ); 430 if (!fpme->post_vs) 431 goto fail; 432 433 fpme->emit = draw_pt_emit_create( draw ); 434 if (!fpme->emit) 435 goto fail; 436 437 fpme->so_emit = draw_pt_so_emit_create( draw ); 438 if (!fpme->so_emit) 439 goto fail; 440 441 fpme->llvm = draw_llvm_create(draw); 442 if (!fpme->llvm) 443 goto fail; 444 445 fpme->variants = NULL; 446 fpme->current_variant = NULL; 447 fpme->nr_variants = 0; 448 449 return &fpme->base; 450 451 fail: 452 if (fpme) 453 llvm_middle_end_destroy( &fpme->base ); 454 455 return NULL; 456} 457