draw_pt_fetch_shade_pipeline_llvm.c revision c3fee80f2b35f6a7e48d6015bfc759c66b7e1a2c
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 *current_variant; 56}; 57 58 59static void 60llvm_middle_end_prepare( struct draw_pt_middle_end *middle, 61 unsigned in_prim, 62 unsigned opt, 63 unsigned *max_vertices ) 64{ 65 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 66 struct draw_context *draw = fpme->draw; 67 struct llvm_vertex_shader *shader = 68 llvm_vertex_shader(draw->vs.vertex_shader); 69 struct draw_llvm_variant_key key; 70 struct draw_llvm_variant *variant = NULL; 71 struct draw_llvm_variant_list_item *li; 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( shader->base.info.num_inputs, 84 shader->base.info.num_outputs + 1 ); 85 86 /* Scan for instanceID system value. 87 */ 88 for (i = 0; i < shader->base.info.num_inputs; i++) { 89 if (shader->base.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, 4096 ); 122 } 123 else { 124 /* limit max fetches by limiting max_vertices */ 125 *max_vertices = 4096; 126 } 127 128 /* return even number */ 129 *max_vertices = *max_vertices & ~1; 130 131 draw_llvm_make_variant_key(fpme->llvm, &key); 132 133 li = first_elem(&shader->variants); 134 while(!at_end(&shader->variants, li)) { 135 if(memcmp(&li->base->key, &key, sizeof key) == 0) { 136 variant = li->base; 137 break; 138 } 139 li = next_elem(li); 140 } 141 142 if (variant) { 143 move_to_head(&fpme->llvm->vs_variants_list, &variant->list_item_global); 144 } 145 else { 146 unsigned i; 147 if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) { 148 /* 149 * XXX: should we flush here ? 150 */ 151 for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) { 152 struct draw_llvm_variant_list_item *item = 153 last_elem(&fpme->llvm->vs_variants_list); 154 draw_llvm_destroy_variant(item->base); 155 } 156 } 157 158 variant = draw_llvm_create_variant(fpme->llvm, nr); 159 160 if (variant) { 161 insert_at_head(&shader->variants, &variant->list_item_local); 162 insert_at_head(&fpme->llvm->vs_variants_list, &variant->list_item_global); 163 fpme->llvm->nr_variants++; 164 shader->variants_cached++; 165 } 166 } 167 168 fpme->current_variant = variant; 169 170 /*XXX we only support one constant buffer */ 171 fpme->llvm->jit_context.vs_constants = 172 draw->pt.user.vs_constants[0]; 173 fpme->llvm->jit_context.gs_constants = 174 draw->pt.user.gs_constants[0]; 175} 176 177 178static void pipeline(struct llvm_middle_end *llvm, 179 const struct draw_vertex_info *vert_info, 180 const struct draw_prim_info *prim_info) 181{ 182 if (prim_info->linear) 183 draw_pipeline_run_linear( llvm->draw, 184 vert_info, 185 prim_info); 186 else 187 draw_pipeline_run( llvm->draw, 188 vert_info, 189 prim_info ); 190} 191 192static void emit(struct pt_emit *emit, 193 const struct draw_vertex_info *vert_info, 194 const struct draw_prim_info *prim_info) 195{ 196 if (prim_info->linear) { 197 draw_pt_emit_linear(emit, vert_info, prim_info); 198 } 199 else { 200 draw_pt_emit(emit, vert_info, prim_info); 201 } 202} 203 204static void 205llvm_pipeline_generic( struct draw_pt_middle_end *middle, 206 const struct draw_fetch_info *fetch_info, 207 const struct draw_prim_info *prim_info ) 208{ 209 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 210 struct draw_context *draw = fpme->draw; 211 struct draw_geometry_shader *gshader = draw->gs.geometry_shader; 212 struct draw_prim_info gs_prim_info; 213 struct draw_vertex_info llvm_vert_info; 214 struct draw_vertex_info gs_vert_info; 215 struct draw_vertex_info *vert_info; 216 unsigned opt = fpme->opt; 217 218 llvm_vert_info.count = fetch_info->count; 219 llvm_vert_info.vertex_size = fpme->vertex_size; 220 llvm_vert_info.stride = fpme->vertex_size; 221 llvm_vert_info.verts = 222 (struct vertex_header *)MALLOC(fpme->vertex_size * 223 align(fetch_info->count, 4)); 224 if (!llvm_vert_info.verts) { 225 assert(0); 226 return; 227 } 228 229 if (fetch_info->linear) 230 fpme->current_variant->jit_func( &fpme->llvm->jit_context, 231 llvm_vert_info.verts, 232 (const char **)draw->pt.user.vbuffer, 233 fetch_info->start, 234 fetch_info->count, 235 fpme->vertex_size, 236 draw->pt.vertex_buffer, 237 draw->instance_id); 238 else 239 fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context, 240 llvm_vert_info.verts, 241 (const char **)draw->pt.user.vbuffer, 242 fetch_info->elts, 243 fetch_info->count, 244 fpme->vertex_size, 245 draw->pt.vertex_buffer, 246 draw->instance_id); 247 248 /* Finished with fetch and vs: 249 */ 250 fetch_info = NULL; 251 vert_info = &llvm_vert_info; 252 253 254 if ((opt & PT_SHADE) && gshader) { 255 draw_geometry_shader_run(gshader, 256 draw->pt.user.gs_constants, 257 draw->pt.user.gs_constants_size, 258 vert_info, 259 prim_info, 260 &gs_vert_info, 261 &gs_prim_info); 262 263 FREE(vert_info->verts); 264 vert_info = &gs_vert_info; 265 prim_info = &gs_prim_info; 266 } 267 268 /* stream output needs to be done before clipping */ 269 draw_pt_so_emit( fpme->so_emit, 270 vert_info, 271 prim_info ); 272 273 if (draw_pt_post_vs_run( fpme->post_vs, vert_info )) { 274 opt |= PT_PIPELINE; 275 } 276 277 /* Do we need to run the pipeline? 278 */ 279 if (opt & PT_PIPELINE) { 280 pipeline( fpme, 281 vert_info, 282 prim_info ); 283 } 284 else { 285 emit( fpme->emit, 286 vert_info, 287 prim_info ); 288 } 289 FREE(vert_info->verts); 290} 291 292 293static void llvm_middle_end_run( struct draw_pt_middle_end *middle, 294 const unsigned *fetch_elts, 295 unsigned fetch_count, 296 const ushort *draw_elts, 297 unsigned draw_count, 298 unsigned prim_flags ) 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 = FALSE; 305 fetch_info.start = 0; 306 fetch_info.elts = fetch_elts; 307 fetch_info.count = fetch_count; 308 309 prim_info.linear = FALSE; 310 prim_info.start = 0; 311 prim_info.count = draw_count; 312 prim_info.elts = draw_elts; 313 prim_info.prim = fpme->input_prim; 314 prim_info.flags = prim_flags; 315 prim_info.primitive_count = 1; 316 prim_info.primitive_lengths = &draw_count; 317 318 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 319} 320 321 322static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle, 323 unsigned start, 324 unsigned count, 325 unsigned prim_flags) 326{ 327 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 328 struct draw_fetch_info fetch_info; 329 struct draw_prim_info prim_info; 330 331 fetch_info.linear = TRUE; 332 fetch_info.start = start; 333 fetch_info.count = count; 334 fetch_info.elts = NULL; 335 336 prim_info.linear = TRUE; 337 prim_info.start = 0; 338 prim_info.count = count; 339 prim_info.elts = NULL; 340 prim_info.prim = fpme->input_prim; 341 prim_info.flags = prim_flags; 342 prim_info.primitive_count = 1; 343 prim_info.primitive_lengths = &count; 344 345 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 346} 347 348 349 350static boolean 351llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle, 352 unsigned start, 353 unsigned count, 354 const ushort *draw_elts, 355 unsigned draw_count, 356 unsigned prim_flags ) 357{ 358 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 359 struct draw_fetch_info fetch_info; 360 struct draw_prim_info prim_info; 361 362 fetch_info.linear = TRUE; 363 fetch_info.start = start; 364 fetch_info.count = count; 365 fetch_info.elts = NULL; 366 367 prim_info.linear = FALSE; 368 prim_info.start = 0; 369 prim_info.count = draw_count; 370 prim_info.elts = draw_elts; 371 prim_info.prim = fpme->input_prim; 372 prim_info.flags = prim_flags; 373 prim_info.primitive_count = 1; 374 prim_info.primitive_lengths = &draw_count; 375 376 llvm_pipeline_generic( middle, &fetch_info, &prim_info ); 377 378 return TRUE; 379} 380 381 382 383static void llvm_middle_end_finish( struct draw_pt_middle_end *middle ) 384{ 385 /* nothing to do */ 386} 387 388static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle ) 389{ 390 struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle; 391 392 if (fpme->fetch) 393 draw_pt_fetch_destroy( fpme->fetch ); 394 395 if (fpme->emit) 396 draw_pt_emit_destroy( fpme->emit ); 397 398 if (fpme->so_emit) 399 draw_pt_so_emit_destroy( fpme->so_emit ); 400 401 if (fpme->post_vs) 402 draw_pt_post_vs_destroy( fpme->post_vs ); 403 404 FREE(middle); 405} 406 407 408struct draw_pt_middle_end * 409draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw) 410{ 411 struct llvm_middle_end *fpme = 0; 412 413 if (!draw->engine) 414 return NULL; 415 416 fpme = CALLOC_STRUCT( llvm_middle_end ); 417 if (!fpme) 418 goto fail; 419 420 fpme->base.prepare = llvm_middle_end_prepare; 421 fpme->base.run = llvm_middle_end_run; 422 fpme->base.run_linear = llvm_middle_end_linear_run; 423 fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts; 424 fpme->base.finish = llvm_middle_end_finish; 425 fpme->base.destroy = llvm_middle_end_destroy; 426 427 fpme->draw = draw; 428 429 fpme->fetch = draw_pt_fetch_create( draw ); 430 if (!fpme->fetch) 431 goto fail; 432 433 fpme->post_vs = draw_pt_post_vs_create( draw ); 434 if (!fpme->post_vs) 435 goto fail; 436 437 fpme->emit = draw_pt_emit_create( draw ); 438 if (!fpme->emit) 439 goto fail; 440 441 fpme->so_emit = draw_pt_so_emit_create( draw ); 442 if (!fpme->so_emit) 443 goto fail; 444 445 fpme->llvm = draw->llvm; 446 if (!fpme->llvm) 447 goto fail; 448 449 fpme->current_variant = NULL; 450 451 return &fpme->base; 452 453 fail: 454 if (fpme) 455 llvm_middle_end_destroy( &fpme->base ); 456 457 return NULL; 458} 459