llvmpipe: Update for TGSI_INTERPOLATE_COLOR.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_state_fs.c
index 6243a96f454a1321f16ddc088ff144ed5f249839..c7bab82b0882bd126f285e8414aa05a9f8ea9a03 100644 (file)
@@ -516,7 +516,6 @@ generate_fragment(struct llvmpipe_context *lp,
    struct lp_type fs_type;
    struct lp_type blend_type;
    LLVMTypeRef fs_elem_type;
-   LLVMTypeRef fs_int_vec_type;
    LLVMTypeRef blend_vec_type;
    LLVMTypeRef arg_types[11];
    LLVMTypeRef func_type;
@@ -594,7 +593,6 @@ generate_fragment(struct llvmpipe_context *lp,
     */
 
    fs_elem_type = lp_build_elem_type(gallivm, fs_type);
-   fs_int_vec_type = lp_build_int_vec_type(gallivm, fs_type);
 
    blend_vec_type = lp_build_vec_type(gallivm, blend_type);
 
@@ -806,6 +804,7 @@ generate_fragment(struct llvmpipe_context *lp,
       LLVMWriteBitcodeToFile(gallivm->module, "llvmpipe.bc");
    }
 
+   variant->nr_instrs += lp_build_count_instructions(function);
    /*
     * Translate the LLVM IR into machine code.
     */
@@ -1026,19 +1025,15 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
       case TGSI_INTERPOLATE_PERSPECTIVE:
         shader->inputs[i].interp = LP_INTERP_PERSPECTIVE;
         break;
+      case TGSI_INTERPOLATE_COLOR:
+        shader->inputs[i].interp = LP_INTERP_COLOR;
+        break;
       default:
         assert(0);
         break;
       }
 
       switch (shader->info.base.input_semantic_name[i]) {
-      case TGSI_SEMANTIC_COLOR:
-         /* Colors may be either linearly or constant interpolated in
-         * the fragment shader, but that information isn't available
-         * here.  Mark color inputs and fix them up later.
-          */
-        shader->inputs[i].interp = LP_INTERP_COLOR;
-         break;
       case TGSI_SEMANTIC_FACE:
         shader->inputs[i].interp = LP_INTERP_FACING;
         break;
@@ -1131,6 +1126,7 @@ llvmpipe_remove_shader_variant(struct llvmpipe_context *lp,
    /* remove from context's list */
    remove_from_list(&variant->list_item_global);
    lp->nr_fs_variants--;
+   lp->nr_fs_instrs -= variant->nr_instrs;
 
    FREE(variant);
 }
@@ -1294,7 +1290,8 @@ make_variant_key(struct llvmpipe_context *lp,
        *
        * Also, force rgb/alpha func/factors match, to make AoS blending easier.
        */
-      if (format_desc->swizzle[3] > UTIL_FORMAT_SWIZZLE_W) {
+      if (format_desc->swizzle[3] > UTIL_FORMAT_SWIZZLE_W ||
+         format_desc->swizzle[3] == format_desc->swizzle[0]) {
          blend_rt->rgb_src_factor   = force_dst_alpha_one(blend_rt->rgb_src_factor);
          blend_rt->rgb_dst_factor   = force_dst_alpha_one(blend_rt->rgb_dst_factor);
          blend_rt->alpha_func       = blend_rt->rgb_func;
@@ -1352,11 +1349,22 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
       /* variant not found, create it now */
       int64_t t0, t1, dt;
       unsigned i;
+      unsigned variants_to_cull;
+
+      if (0) {
+         debug_printf("%u variants,\t%u instrs,\t%u instrs/variant\n",
+                      lp->nr_fs_variants,
+                      lp->nr_fs_instrs,
+                      lp->nr_fs_variants ? lp->nr_fs_instrs / lp->nr_fs_variants : 0);
+      }
 
       /* First, check if we've exceeded the max number of shader variants.
        * If so, free 25% of them (the least recently used ones).
        */
-      if (lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS) {
+      variants_to_cull = lp->nr_fs_variants >= LP_MAX_SHADER_VARIANTS ? LP_MAX_SHADER_VARIANTS / 4 : 0;
+
+      if (variants_to_cull ||
+          lp->nr_fs_instrs >= LP_MAX_SHADER_INSTRUCTIONS) {
          struct pipe_context *pipe = &lp->pipe;
 
          /*
@@ -1366,9 +1374,20 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
           */
          llvmpipe_finish(pipe, __FUNCTION__);
 
-         for (i = 0; i < LP_MAX_SHADER_VARIANTS / 4; i++) {
+         /*
+          * We need to re-check lp->nr_fs_variants because an arbitrarliy large
+          * number of shader variants (potentially all of them) could be
+          * pending for destruction on flush.
+          */
+
+         for (i = 0; i < variants_to_cull || lp->nr_fs_instrs >= LP_MAX_SHADER_INSTRUCTIONS; i++) {
             struct lp_fs_variant_list_item *item;
+            if (is_empty_list(&lp->fs_variants_list)) {
+               break;
+            }
             item = last_elem(&lp->fs_variants_list);
+            assert(item);
+            assert(item->base);
             llvmpipe_remove_shader_variant(lp, item->base);
          }
       }
@@ -1390,6 +1409,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
          insert_at_head(&shader->variants, &variant->list_item_local);
          insert_at_head(&lp->fs_variants_list, &variant->list_item_global);
          lp->nr_fs_variants++;
+         lp->nr_fs_instrs += variant->nr_instrs;
          shader->variants_cached++;
       }
    }