draw llvm: highly reduce the compilation times for draw llvm
authorZack Rusin <zackr@vmware.com>
Wed, 7 Apr 2010 21:46:55 +0000 (17:46 -0400)
committerZack Rusin <zackr@vmware.com>
Wed, 7 Apr 2010 21:50:11 +0000 (17:50 -0400)
our code resets pipe_vertex_buffer's with different offsets when rendering
vbo, meaning that we kept creating insane number of shaders even for simple
apps e.g. geartrain had 54 shaders and it was taking almost 27 seconds just to
compile them. this patch passes pipe_vertex_buffer's to the jit function and lets
it to the stride/buffer_offset computation at run time. the slowdown at runtime
is largely unnoticable but the we go from 54 shaders to 3, and from 27 seconds to less
than 1.

src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/draw/draw_llvm.h
src/gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c

index 3a4e14c7a21e61ae9c3581e2b8c2e54c1e2e2244..be73a6784828bcf85166f0e8cb8a09d813abe799 100644 (file)
@@ -90,6 +90,29 @@ init_globals(struct draw_llvm *llvm)
       LLVMTypeRef buffer_ptr = LLVMPointerType(LLVMIntType(8), 0);
       llvm->buffer_ptr_type = LLVMPointerType(buffer_ptr, 0);
    }
+   /* struct pipe_vertex_buffer */
+   {
+      LLVMTypeRef elem_types[4];
+      LLVMTypeRef vb_type;
+
+      elem_types[0] = LLVMInt32Type();
+      elem_types[1] = LLVMInt32Type();
+      elem_types[2] = LLVMInt32Type();
+      elem_types[3] = LLVMPointerType(LLVMOpaqueType(), 0); /* vs_constants */
+
+      vb_type = LLVMStructType(elem_types, Elements(elem_types), 0);
+
+      LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, stride,
+                             llvm->target, vb_type, 0);
+      LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, buffer_offset,
+                             llvm->target, vb_type, 2);
+      LP_CHECK_STRUCT_SIZE(struct pipe_vertex_buffer,
+                           llvm->target, vb_type);
+
+      LLVMAddTypeName(llvm->module, "pipe_vertex_buffer", vb_type);
+
+      llvm->vb_ptr_type = LLVMPointerType(vb_type, 0);
+   }
 }
 
 static LLVMTypeRef
@@ -241,7 +264,7 @@ generate_vs(struct draw_llvm *llvm,
    num_vs = 4;              /* number of vertices per block */
 #endif
 
-   tgsi_dump(tokens, 0);
+   /*tgsi_dump(tokens, 0);*/
    lp_build_tgsi_soa(builder,
                      tokens,
                      vs_type,
@@ -276,20 +299,22 @@ generate_fetch(LLVMBuilderRef builder,
                LLVMValueRef vbuffers_ptr,
                LLVMValueRef *res,
                struct pipe_vertex_element *velem,
-               struct pipe_vertex_buffer *vbuf,
+               LLVMValueRef vbuf,
                LLVMValueRef index)
 {
    LLVMValueRef indices = LLVMConstInt(LLVMInt64Type(), velem->vertex_buffer_index, 0);
    LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr,
                                            &indices, 1, "");
+   LLVMValueRef vb_stride = draw_jit_vbuffer_stride(builder, vbuf);
+   LLVMValueRef vb_buffer_offset = draw_jit_vbuffer_offset(builder, vbuf);
    LLVMValueRef stride = LLVMBuildMul(builder,
-                                      LLVMConstInt(LLVMInt32Type(), vbuf->stride, 0),
+                                      vb_stride,
                                       index, "");
 
    vbuffer_ptr = LLVMBuildLoad(builder, vbuffer_ptr, "vbuffer");
 
    stride = LLVMBuildAdd(builder, stride,
-                         LLVMConstInt(LLVMInt32Type(), vbuf->buffer_offset, 0),
+                         vb_buffer_offset,
                          "");
    stride = LLVMBuildAdd(builder, stride,
                          LLVMConstInt(LLVMInt32Type(), velem->src_offset, 0),
@@ -549,13 +574,13 @@ convert_to_aos(LLVMBuilderRef builder,
 static void
 draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
 {
-   LLVMTypeRef arg_types[6];
+   LLVMTypeRef arg_types[7];
    LLVMTypeRef func_type;
    LLVMValueRef context_ptr;
    LLVMBasicBlockRef block;
    LLVMBuilderRef builder;
    LLVMValueRef start, end, count, stride, step, io_itr;
-   LLVMValueRef io_ptr, vbuffers_ptr;
+   LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
    struct draw_context *draw = llvm->draw;
    unsigned i, j;
    struct lp_build_context bld;
@@ -570,6 +595,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    arg_types[3] = LLVMInt32Type();                  /* start */
    arg_types[4] = LLVMInt32Type();                  /* count */
    arg_types[5] = LLVMInt32Type();                  /* stride */
+   arg_types[6] = llvm->vb_ptr_type;                /* pipe_vertex_buffer's */
 
    func_type = LLVMFunctionType(LLVMVoidType(), arg_types, Elements(arg_types), 0);
 
@@ -585,6 +611,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    start        = LLVMGetParam(variant->function, 3);
    count        = LLVMGetParam(variant->function, 4);
    stride       = LLVMGetParam(variant->function, 5);
+   vb_ptr       = LLVMGetParam(variant->function, 6);
 
    lp_build_name(context_ptr, "context");
    lp_build_name(io_ptr, "io");
@@ -592,6 +619,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    lp_build_name(start, "start");
    lp_build_name(count, "count");
    lp_build_name(stride, "stride");
+   lp_build_name(vb_ptr, "vb");
 
    /*
     * Function body
@@ -631,10 +659,13 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
             LLVMConstInt(LLVMInt32Type(), i, 0), "");
          for (j = 0; j < draw->pt.nr_vertex_elements; ++j) {
             struct pipe_vertex_element *velem = &draw->pt.vertex_element[j];
-            struct pipe_vertex_buffer *vbuf = &draw->pt.vertex_buffer[
-               velem->vertex_buffer_index];
+            LLVMValueRef vb_index = LLVMConstInt(LLVMInt32Type(),
+                                                 velem->vertex_buffer_index,
+                                                 0);
+            LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr,
+                                           &vb_index, 0, "");
             generate_fetch(builder, vbuffers_ptr,
-                           &aos_attribs[j][i], velem, vbuf, true_index);
+                           &aos_attribs[j][i], velem, vb, true_index);
          }
       }
       convert_to_soa(builder, aos_attribs, inputs,
@@ -660,7 +691,6 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    /*
     * Translate the LLVM IR into machine code.
     */
-
 #ifdef DEBUG
    if(LLVMVerifyFunction(variant->function, LLVMPrintMessageAction)) {
       LLVMDumpValue(variant->function);
@@ -684,16 +714,13 @@ 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;
+   memset(key, 0, sizeof(struct draw_llvm_variant_key));
 
-   memcpy(key->vertex_buffer,
-          llvm->draw->pt.vertex_buffer,
-          sizeof(struct pipe_vertex_buffer) * PIPE_MAX_ATTRIBS);
+   key->nr_vertex_elements = llvm->draw->pt.nr_vertex_elements;
 
    memcpy(key->vertex_element,
           llvm->draw->pt.vertex_element,
-          sizeof(struct pipe_vertex_element) * PIPE_MAX_ATTRIBS);
+          sizeof(struct pipe_vertex_element) * key->nr_vertex_elements);
 
    memcpy(&key->vs,
           &llvm->draw->vs.vertex_shader->state,
index 774eb16d90c292369c2b51dfd56324b2ece0c47c..d1cbac4af97025d21d83f542fe57d35a01ca2103 100644 (file)
@@ -74,54 +74,13 @@ struct draw_jit_context
 #define draw_jit_header_data(_builder, _ptr)            \
    lp_build_struct_get_ptr(_builder, _ptr, 2, "data")
 
-/* we are construction a function of the form:
 
-struct vertex_header {
-   uint32 vertex_id;
+#define draw_jit_vbuffer_stride(_builder, _ptr)         \
+   lp_build_struct_get(_builder, _ptr, 0, "stride")
 
-   float clip[4];
-   float data[][4];
-};
-
-struct draw_jit_context
-{
-   const float *vs_constants;
-   const float *gs_constants;
+#define draw_jit_vbuffer_offset(_builder, _ptr)                 \
+   lp_build_struct_get(_builder, _ptr, 2, "buffer_offset")
 
-   struct draw_jit_texture textures[PIPE_MAX_SAMPLERS];
-};
-
-void
-draw_shader(struct draw_jit_context *context,
-            struct vertex_header *io,
-            const void *vbuffers[PIPE_MAX_ATTRIBS],
-            unsigned start,
-            unsigned count,
-            unsigned stride)
-{
-  // do a fetch and a run vertex shader
-  for (int i = 0; i < count; ++i) {
-    struct vertex_header *header = &io[i];
-    header->vertex_id = 0xffff;
-    // follows code-genarted fetch/translate section
-    // for each vertex_element ...
-    codegened_translate(header->data[num_element],
-                       context->vertex_elements[num_element],
-                       context->vertex_buffers,
-                       context->vbuffers);
-
-    codegened_vertex_shader(header->data, context->vs_constants);
-  }
-
-  for (int i = 0; i < count; i += context->primitive_size) {
-     struct vertex_header *prim[MAX_PRIMITIVE_SIZE];
-     for (int j = 0; j < context->primitive_size; ++j) {
-       header[j] = &io[i + j];
-     }
-     codegened_geometry_shader(prim, gs_constants);
-  }
-}
-*/
 
 typedef void
 (*draw_jit_vert_func)(struct draw_jit_context *context,
@@ -129,7 +88,8 @@ typedef void
                       const char *vbuffers[PIPE_MAX_ATTRIBS],
                       unsigned start,
                       unsigned count,
-                      unsigned stride);
+                      unsigned stride,
+                      struct pipe_vertex_buffer *vertex_buffers);
 
 struct draw_llvm {
    struct draw_context *draw;
@@ -145,15 +105,13 @@ struct draw_llvm {
    LLVMTypeRef context_ptr_type;
    LLVMTypeRef vertex_header_ptr_type;
    LLVMTypeRef buffer_ptr_type;
+   LLVMTypeRef vb_ptr_type;
 };
 
-
 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;
+   unsigned                   nr_vertex_elements;
    struct pipe_shader_state   vs;
 };
 
index aa34a3ea5fdc7390cabaced7941a56d0a808d933..42dcc0886f3b973e44225ecd5438364691360dd6 100644 (file)
@@ -53,6 +53,7 @@ struct llvm_middle_end {
    struct draw_llvm *llvm;
    struct draw_llvm_variant *variants;
    struct draw_llvm_variant *current_variant;
+   int nr_variants;
 };
 
 
@@ -145,6 +146,7 @@ llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
       variant = draw_llvm_prepare(fpme->llvm, nr);
       variant->next = fpme->variants;
       fpme->variants = variant;
+      ++fpme->nr_variants;
    }
    fpme->current_variant = variant;
 
@@ -271,7 +273,8 @@ static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
                                     (const char **)draw->pt.user.vbuffer,
                                     start,
                                     count,
-                                    fpme->vertex_size );
+                                    fpme->vertex_size,
+                                    draw->pt.vertex_buffer );
 
    if (draw_pt_post_vs_run( fpme->post_vs,
                            pipeline_verts,
@@ -451,6 +454,7 @@ struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm( struct draw_cont
 
    fpme->variants = NULL;
    fpme->current_variant = NULL;
+   fpme->nr_variants = 0;
 
    return &fpme->base;