From 323fdd8ae5baf16df6c57754e58adc8e22d28e10 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Tue, 6 Apr 2010 16:28:48 -0400 Subject: [PATCH] draw llvm: implement simple pipeline caching using variants --- src/gallium/auxiliary/draw/draw_llvm.c | 75 +++++++++++++------ src/gallium/auxiliary/draw/draw_llvm.h | 27 +++++-- .../draw/draw_pt_fetch_shade_pipeline_llvm.c | 36 +++++++-- 3 files changed, 103 insertions(+), 35 deletions(-) diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index a09e2a9f0c2..26f756c6f8a 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -17,7 +17,12 @@ #include -#define DEBUG_STORE 1 +#define DEBUG_STORE 0 + + +/* generates the draw jit function */ +static void +draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *var); static void init_globals(struct draw_llvm *llvm) @@ -179,11 +184,18 @@ draw_llvm_destroy(struct draw_llvm *llvm) free(llvm); } -void +struct draw_llvm_variant * draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs) { + struct draw_llvm_variant *variant = MALLOC(sizeof(struct draw_llvm_variant)); + + draw_llvm_make_variant_key(llvm, &variant->key); + llvm->vertex_header_ptr_type = create_vertex_header(llvm, num_inputs); - draw_llvm_generate(llvm); + + draw_llvm_generate(llvm, variant); + + return variant; } @@ -530,15 +542,14 @@ convert_to_aos(LLVMBuilderRef builder, #endif } -void -draw_llvm_generate(struct draw_llvm *llvm) +static void +draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant) { LLVMTypeRef arg_types[6]; LLVMTypeRef func_type; LLVMValueRef context_ptr; LLVMBasicBlockRef block; LLVMBuilderRef builder; - LLVMValueRef function; LLVMValueRef start, end, count, stride, step, io_itr; LLVMValueRef io_ptr, vbuffers_ptr; struct draw_context *draw = llvm->draw; @@ -558,18 +569,18 @@ draw_llvm_generate(struct draw_llvm *llvm) func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0); - function = LLVMAddFunction(llvm->module, "draw_llvm_shader", func_type); - LLVMSetFunctionCallConv(function, LLVMCCallConv); + variant->function = LLVMAddFunction(llvm->module, "draw_llvm_shader", func_type); + LLVMSetFunctionCallConv(variant->function, LLVMCCallConv); for(i = 0; i < Elements(arg_types); ++i) if(LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind) - LLVMAddAttribute(LLVMGetParam(function, i), LLVMNoAliasAttribute); + LLVMAddAttribute(LLVMGetParam(variant->function, i), LLVMNoAliasAttribute); - context_ptr = LLVMGetParam(function, 0); - io_ptr = LLVMGetParam(function, 1); - vbuffers_ptr = LLVMGetParam(function, 2); - start = LLVMGetParam(function, 3); - count = LLVMGetParam(function, 4); - stride = LLVMGetParam(function, 5); + context_ptr = LLVMGetParam(variant->function, 0); + io_ptr = LLVMGetParam(variant->function, 1); + vbuffers_ptr = LLVMGetParam(variant->function, 2); + start = LLVMGetParam(variant->function, 3); + count = LLVMGetParam(variant->function, 4); + stride = LLVMGetParam(variant->function, 5); lp_build_name(context_ptr, "context"); lp_build_name(io_ptr, "io"); @@ -582,7 +593,7 @@ draw_llvm_generate(struct draw_llvm *llvm) * Function body */ - block = LLVMAppendBasicBlock(function, "entry"); + block = LLVMAppendBasicBlock(variant->function, "entry"); builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, block); @@ -647,20 +658,40 @@ draw_llvm_generate(struct draw_llvm *llvm) */ #ifdef DEBUG - if(LLVMVerifyFunction(function, LLVMPrintMessageAction)) { - LLVMDumpValue(function); + if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) { + LLVMDumpValue(variant->function); assert(0); } #endif - LLVMRunFunctionPassManager(llvm->pass, function); + LLVMRunFunctionPassManager(llvm->pass, variant->function); if (1) { - LLVMDumpValue(function); + LLVMDumpValue(variant->function); debug_printf("\n"); } - llvm->jit_func = (draw_jit_vert_func)LLVMGetPointerToGlobal(llvm->draw->engine, function); + variant->jit_func = (draw_jit_vert_func)LLVMGetPointerToGlobal(llvm->draw->engine, variant->function); if (1) - lp_disassemble(llvm->jit_func); + lp_disassemble(variant->jit_func); +} + +void +draw_llvm_make_variant_key(struct draw_llvm *llvm, + struct draw_llvm_variant_key *key) +{ + key->nr_vertex_buffers = llvm->draw->pt.nr_vertex_buffers; + key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements; + + memcpy(key->vertex_buffer, + llvm->draw->pt.vertex_buffer, + sizeof(struct pipe_vertex_buffer) * PIPE_MAX_ATTRIBS); + + memcpy(key->vertex_element, + llvm->draw->pt.vertex_element, + sizeof(struct pipe_vertex_element) * PIPE_MAX_ATTRIBS); + + memcpy(&key->vs, + &llvm->draw->vs.vertex_shader->state, + sizeof(struct pipe_shader_state)); } diff --git a/src/gallium/auxiliary/draw/draw_llvm.h b/src/gallium/auxiliary/draw/draw_llvm.h index afafa15e687..774eb16d90c 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.h +++ b/src/gallium/auxiliary/draw/draw_llvm.h @@ -136,8 +136,6 @@ struct draw_llvm { struct draw_jit_context jit_context; - draw_jit_vert_func jit_func; - LLVMModuleRef module; LLVMExecutionEngineRef engine; LLVMModuleProviderRef provider; @@ -150,22 +148,39 @@ struct draw_llvm { }; +struct draw_llvm_variant_key +{ + struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS]; + unsigned nr_vertex_buffers; + struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS]; + unsigned nr_vertex_elements; + struct pipe_shader_state vs; +}; + +struct draw_llvm_variant +{ + struct draw_llvm_variant_key key; + LLVMValueRef function; + draw_jit_vert_func jit_func; + + struct draw_llvm_variant *next; +}; + struct draw_llvm * draw_llvm_create(struct draw_context *draw); void draw_llvm_destroy(struct draw_llvm *llvm); -void +struct draw_llvm_variant * draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs); -/* generates the draw jit function */ void -draw_llvm_generate(struct draw_llvm *llvm); +draw_llvm_make_variant_key(struct draw_llvm *llvm, + struct draw_llvm_variant_key *key); LLVMValueRef draw_llvm_translate_from(LLVMBuilderRef builder, LLVMValueRef vbuffer, enum pipe_format from_format); - #endif diff --git a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c index 307e6cc3a4d..0ed043d9506 100644 --- a/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c +++ b/src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c @@ -53,6 +53,8 @@ struct llvm_middle_end { unsigned opt; struct draw_llvm *llvm; + struct draw_llvm_variant *variants; + struct draw_llvm_variant *current_variant; }; @@ -66,6 +68,8 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, struct draw_context *draw = fpme->draw; struct draw_vertex_shader *vs = draw->vs.vertex_shader; struct draw_geometry_shader *gs = draw->gs.geometry_shader; + struct draw_llvm_variant_key key; + struct draw_llvm_variant *variant = NULL; unsigned i; unsigned instance_id_index = ~0; @@ -129,7 +133,22 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle, /* return even number */ *max_vertices = *max_vertices & ~1; - draw_llvm_prepare(fpme->llvm, nr); + draw_llvm_make_variant_key(fpme->llvm, &key); + + variant = fpme->variants; + while(variant) { + if(memcmp(&variant->key, &key, sizeof key) == 0) + break; + + variant = variant->next; + } + + if (!variant) { + variant = draw_llvm_prepare(fpme->llvm, nr); + variant->next = fpme->variants; + fpme->variants = variant; + } + fpme->current_variant = variant; /*XXX we only support one constant buffer */ fpme->llvm->jit_context.vs_constants = @@ -247,12 +266,12 @@ static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle, debug_printf("#### Pipeline = %p (data = %p)\n", pipeline_verts, pipeline_verts->data); - fpme->llvm->jit_func( &fpme->llvm->jit_context, - pipeline_verts, - (const char **)draw->pt.user.vbuffer, - start, - count, - fpme->vertex_size ); + fpme->current_variant->jit_func( &fpme->llvm->jit_context, + pipeline_verts, + (const char **)draw->pt.user.vbuffer, + start, + count, + fpme->vertex_size ); if (draw_pt_post_vs_run( fpme->post_vs, pipeline_verts, @@ -430,6 +449,9 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_cont if (!fpme->llvm) goto fail; + fpme->variants = NULL; + fpme->current_variant = NULL; + return &fpme->base; fail: -- 2.30.2