Merge branch 'draw-instanced'
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_tgsi_soa.c
index ab86cc4ab7a7480bd03bfa2a6f28f6592dca5df8..d1585c8e2b7598a667140eedc82504f2a53d3f45 100644 (file)
@@ -157,6 +157,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;
@@ -535,7 +537,7 @@ emit_mask_scatter(struct lp_build_tgsi_soa_context *bld,
                   LLVMValueRef pred)
 {
    struct gallivm_state *gallivm = bld->base.gallivm;
-   LLVMBuilderRef builder = builder;
+   LLVMBuilderRef builder = gallivm->builder;
    unsigned i;
 
    /* Mix the predicate and execution mask */
@@ -759,6 +761,23 @@ 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(gallivm,
+                                      reg->Register.Index * 4 + swizzle);
+
+         scalar_ptr = LLVMBuildGEP(builder, bld->system_values_array,
+                                   &index, 1, "");
+         scalar = LLVMBuildLoad(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;
@@ -895,6 +914,7 @@ emit_store(
    LLVMValueRef value)
 {
    struct gallivm_state *gallivm = bld->base.gallivm;
+   LLVMBuilderRef builder = gallivm->builder;
    const struct tgsi_full_dst_register *reg = &inst->Dst[index];
    struct lp_build_context *uint_bld = &bld->uint_bld;
    LLVMValueRef indirect_index = NULL;
@@ -929,7 +949,6 @@ emit_store(
    switch( reg->Register.File ) {
    case TGSI_FILE_OUTPUT:
       if (reg->Register.Indirect) {
-         LLVMBuilderRef builder = builder;
          LLVMValueRef chan_vec =
             lp_build_const_int_vec(gallivm, uint_bld->type, chan_index);
          LLVMValueRef length_vec =
@@ -972,7 +991,6 @@ emit_store(
 
    case TGSI_FILE_TEMPORARY:
       if (reg->Register.Indirect) {
-         LLVMBuilderRef builder = builder;
          LLVMValueRef chan_vec =
             lp_build_const_int_vec(gallivm, uint_bld->type, chan_index);
          LLVMValueRef length_vec =
@@ -2323,6 +2341,7 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
                   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],
@@ -2412,6 +2431,8 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
       }
    }
 
+   bld.system_values_array = system_values_array;
+
    tgsi_parse_init( &parse, tokens );
 
    while( !tgsi_parse_end_of_tokens( &parse ) ) {
@@ -2513,3 +2534,54 @@ lp_build_tgsi_soa(struct gallivm_state *gallivm,
    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(struct gallivm_state *gallivm,
+                             const struct tgsi_shader_info *info,
+                             LLVMValueRef instance_id,
+                             LLVMValueRef facing)
+{
+   LLVMValueRef size = lp_build_const_int32(gallivm, 4 * info->num_system_values);
+   LLVMTypeRef float_t = LLVMFloatTypeInContext(gallivm->context);
+   LLVMValueRef array = lp_build_array_alloca(gallivm, float_t,
+                                              size, "sysvals_array");
+   unsigned i;
+
+   for (i = 0; i < info->num_system_values; i++) {
+      LLVMValueRef index = lp_build_const_int32(gallivm, 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(gallivm->builder, instance_id, float_t,
+                                 "sysval_instanceid");
+         break;
+      case TGSI_SEMANTIC_FACE:
+         /* fall-through */
+      default:
+         assert(0 && "unexpected semantic in build_system_values_array()");
+      }
+
+      ptr = LLVMBuildGEP(gallivm->builder, array, &index, 1, "");
+      LLVMBuildStore(gallivm->builder, value, ptr);
+   }
+      
+   return array;
+}