gallivm/llvmpipe: implement system values and instanceID
authorBrian Paul <brianp@vmware.com>
Thu, 9 Dec 2010 02:02:14 +0000 (19:02 -0700)
committerBrian Paul <brianp@vmware.com>
Thu, 9 Dec 2010 02:04:11 +0000 (19:04 -0700)
src/gallium/auxiliary/draw/draw_llvm.c
src/gallium/auxiliary/gallivm/lp_bld_tgsi.h
src/gallium/auxiliary/gallivm/lp_bld_tgsi_soa.c
src/gallium/drivers/llvmpipe/lp_state_fs.c

index 2b5f01cda74c4091d77e0faf39eea1883e40578f..eb162fb0f6263458063678f994d36d22b762d074 100644 (file)
@@ -340,6 +340,7 @@ generate_vs(struct draw_llvm *llvm,
             LLVMBuilderRef builder,
             LLVMValueRef (*outputs)[NUM_CHANNELS],
             const LLVMValueRef (*inputs)[NUM_CHANNELS],
+            LLVMValueRef system_values_array,
             LLVMValueRef context_ptr,
             struct lp_build_sampler_soa *draw_sampler)
 {
@@ -371,6 +372,7 @@ generate_vs(struct draw_llvm *llvm,
                      vs_type,
                      NULL /*struct lp_build_mask_context *mask*/,
                      consts_ptr,
+                     system_values_array,
                      NULL /*pos*/,
                      inputs,
                      outputs,
@@ -1011,7 +1013,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
    LLVMValueRef start, end, count, stride, step, io_itr;
    LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
    LLVMValueRef instance_id;
+   LLVMValueRef system_values_array;
    struct draw_context *draw = llvm->draw;
+   const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info;
    unsigned i, j;
    struct lp_build_context bld;
    struct lp_build_loop_state lp_loop;
@@ -1070,6 +1074,9 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
 
    lp_build_context_init(&bld, builder, lp_type_int(32));
 
+   system_values_array = lp_build_system_values_array(builder, vs_info,
+                                                      instance_id, NULL);
+
    end = lp_build_add(&bld, start, count);
 
    step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
@@ -1126,6 +1133,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
                   builder,
                   outputs,
                   ptr_aos,
+                  system_values_array,
                   context_ptr,
                   sampler);
 
@@ -1156,8 +1164,7 @@ draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant)
 
       /* store clipmask in vertex header and positions in data */
       convert_to_aos(builder, io, outputs, clipmask,
-                     draw->vs.vertex_shader->info.num_outputs,
-                     max_vertices);
+                     vs_info->num_outputs, max_vertices);
    }
 
    lp_build_loop_end_cond(builder, end, step, LLVMIntUGE, &lp_loop);
@@ -1207,7 +1214,9 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
    LLVMValueRef fetch_elts, fetch_count, stride, step, io_itr;
    LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
    LLVMValueRef instance_id;
+   LLVMValueRef system_values_array;
    struct draw_context *draw = llvm->draw;
+   const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info;
    unsigned i, j;
    struct lp_build_context bld;
    struct lp_build_loop_state lp_loop;
@@ -1268,6 +1277,10 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
 
    lp_build_context_init(&bld, builder, lp_type_int(32));
 
+   system_values_array = lp_build_system_values_array(builder, vs_info,
+                                                      instance_id, NULL);
+
+
    step = LLVMConstInt(LLVMInt32Type(), max_vertices, 0);
 
    /* code generated texture sampling */
@@ -1332,6 +1345,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
                   builder,
                   outputs,
                   ptr_aos,
+                  system_values_array,
                   context_ptr,
                   sampler);
 
@@ -1365,8 +1379,7 @@ draw_llvm_generate_elts(struct draw_llvm *llvm, struct draw_llvm_variant *varian
        * and transformed positions in data 
        */   
       convert_to_aos(builder, io, outputs, clipmask,
-                     draw->vs.vertex_shader->info.num_outputs,
-                     max_vertices);
+                     vs_info->num_outputs, max_vertices);
    }
 
    lp_build_loop_end_cond(builder, fetch_count, step, LLVMIntUGE, &lp_loop);
index a4d3b750c3cfa36f8d75d781024e287297ea7dc5..694818ccfb8350d7c3af96cebfcec64968f32a15 100644 (file)
@@ -179,6 +179,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
                   struct lp_type type,
                   struct lp_build_mask_context *mask,
                   LLVMValueRef consts_ptr,
+                  LLVMValueRef system_values_array,
                   const LLVMValueRef *pos,
                   const LLVMValueRef (*inputs)[4],
                   LLVMValueRef (*outputs)[4],
@@ -198,4 +199,11 @@ lp_build_tgsi_aos(LLVMBuilderRef builder,
                   const struct tgsi_shader_info *info);
 
 
+LLVMValueRef
+lp_build_system_values_array(LLVMBuilderRef builder,
+                             const struct tgsi_shader_info *info,
+                             LLVMValueRef instance_id,
+                             LLVMValueRef facing);
+
+
 #endif /* LP_BLD_TGSI_H */
index 7f0f058c2225d75dd53fca86bec148f486f690e6..3fdfac95a0a195dd66f0d92b66135c1ebf82f52c 100644 (file)
@@ -156,6 +156,8 @@ struct lp_build_tgsi_soa_context
     */
    LLVMValueRef inputs_array;
 
+   LLVMValueRef system_values_array;
+
    const struct tgsi_shader_info *info;
    /** bitmask indicating which register files are accessed indirectly */
    unsigned indirect_files;
@@ -732,6 +734,22 @@ emit_fetch(
       }
       break;
 
+   case TGSI_FILE_SYSTEM_VALUE:
+      assert(!reg->Register.Indirect);
+      {
+         LLVMValueRef index;  /* index into the system value array */
+         LLVMValueRef scalar, scalar_ptr;
+
+         index = lp_build_const_int32(reg->Register.Index * 4 + swizzle);
+
+         scalar_ptr = LLVMBuildGEP(bld->base.builder, bld->system_values_array,
+                                   &index, 1, "");
+         scalar = LLVMBuildLoad(bld->base.builder, scalar_ptr, "");
+
+         res = lp_build_broadcast_scalar(&bld->base, scalar);
+      }
+      break;
+
    default:
       assert(0 && "invalid src register in emit_fetch()");
       return bld->base.undef;
@@ -2289,6 +2307,7 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
                   struct lp_type type,
                   struct lp_build_mask_context *mask,
                   LLVMValueRef consts_ptr,
+                  LLVMValueRef system_values_array,
                   const LLVMValueRef *pos,
                   const LLVMValueRef (*inputs)[NUM_CHANNELS],
                   LLVMValueRef (*outputs)[NUM_CHANNELS],
@@ -2375,6 +2394,8 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
       }
    }
 
+   bld.system_values_array = system_values_array;
+
    tgsi_parse_init( &parse, tokens );
 
    while( !tgsi_parse_end_of_tokens( &parse ) ) {
@@ -2476,3 +2497,53 @@ lp_build_tgsi_soa(LLVMBuilderRef builder,
    FREE( bld.instructions );
 }
 
+
+/**
+ * Build up the system values array out of individual values such as
+ * the instance ID, front-face, primitive ID, etc.  The shader info is
+ * used to determine which system values are needed and where to put
+ * them in the system values array.
+ *
+ * XXX only instance ID is implemented at this time.
+ *
+ * The system values register file is similar to the constants buffer.
+ * Example declaration:
+ *    DCL SV[0], INSTANCEID
+ * Example instruction:
+ *    MOVE foo, SV[0].xxxx;
+ *
+ * \return  LLVM float array (interpreted as float [][4])
+ */
+LLVMValueRef
+lp_build_system_values_array(LLVMBuilderRef builder,
+                             const struct tgsi_shader_info *info,
+                             LLVMValueRef instance_id,
+                             LLVMValueRef facing)
+{
+   LLVMValueRef size = lp_build_const_int32(4 * info->num_system_values);
+   LLVMValueRef array = lp_build_array_alloca(builder, LLVMFloatType(),
+                                              size, "sysvals_array");
+   unsigned i;
+
+   for (i = 0; i < info->num_system_values; i++) {
+      LLVMValueRef index = lp_build_const_int32(i * 4);
+      LLVMValueRef ptr, value;
+
+      switch (info->system_value_semantic_name[i]) {
+      case TGSI_SEMANTIC_INSTANCEID:
+         /* convert instance ID from int to float */
+         value = LLVMBuildSIToFP(builder, instance_id, LLVMFloatType(),
+                                 "sysval_instanceid");
+         break;
+      case TGSI_SEMANTIC_FACE:
+         /* fall-through */
+      default:
+         assert(0 && "unexpected semantic in build_system_values_array()");
+      }
+
+      ptr = LLVMBuildGEP(builder, array, &index, 1, "");
+      LLVMBuildStore(builder, value, ptr);
+   }
+      
+   return array;
+}
index 48971510f213d9822b7807c81d062abea18c4c40..cd67d4886163ca74211d9b8568745954206cfbe6 100644 (file)
@@ -334,7 +334,8 @@ generate_fs(struct lp_fragment_shader *shader,
    
    /* Build the actual shader */
    lp_build_tgsi_soa(builder, tokens, type, &mask,
-                     consts_ptr, interp->pos, interp->inputs,
+                     consts_ptr, NULL, /* sys values array */
+                     interp->pos, interp->inputs,
                      outputs, sampler, &shader->info.base);