llvmpipe: Implement cylindrical wrapping.
authorJames Benton <jbenton@vmware.com>
Mon, 18 Jun 2012 16:31:39 +0000 (17:31 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Mon, 18 Jun 2012 16:55:05 +0000 (17:55 +0100)
Tested against mesa demos cylwrap and dx9 DCT address.exe which now passes 100%.

Signed-off-by: José Fonseca <jfonseca@vmware.com>
src/gallium/drivers/llvmpipe/lp_bld_interp.h
src/gallium/drivers/llvmpipe/lp_state_fs.c
src/gallium/drivers/llvmpipe/lp_state_setup.c

index b0cbd9bdaecca8eb078458919abce1237e5ce038..6970a9b8c2cbab01d95fff0313f6cb8187dbd95e 100644 (file)
@@ -67,9 +67,11 @@ enum lp_interp {
 };
 
 struct lp_shader_input {
-   ushort interp:4;       /* enum lp_interp */
-   ushort usage_mask:4;   /* bitmask of TGSI_WRITEMASK_x flags */
-   ushort src_index:8;    /* where to find values in incoming vertices */
+   uint interp:4;       /* enum lp_interp */
+   uint usage_mask:4;   /* bitmask of TGSI_WRITEMASK_x flags */
+   uint src_index:8;    /* where to find values in incoming vertices */
+   uint cyl_wrap:4;     /* TGSI_CYLINDRICAL_WRAP_x flags */
+   uint padding:12;
 };
 
 
index 0bdc17fb3e1017631f97f1e99071a85cb75fd049..7dd4969105173fe6f244fcfecf91b2c544fcd644 100644 (file)
@@ -1014,6 +1014,7 @@ llvmpipe_create_fs_state(struct pipe_context *pipe,
 
    for (i = 0; i < shader->info.base.num_inputs; i++) {
       shader->inputs[i].usage_mask = shader->info.base.input_usage_mask[i];
+      shader->inputs[i].cyl_wrap = shader->info.base.input_cylindrical_wrap[i];
 
       switch (shader->info.base.input_interpolate[i]) {
       case TGSI_INTERPOLATE_CONSTANT:
index 212bc1b9d05f49074cc1a427f757a9d3a7d8a4db..299c1ef85dc567c63487fbf6c104c40f36fc6b77 100644 (file)
@@ -34,6 +34,7 @@
 #include "gallivm/lp_bld_const.h"
 #include "gallivm/lp_bld_debug.h"
 #include "gallivm/lp_bld_init.h"
+#include "gallivm/lp_bld_logic.h"
 #include "gallivm/lp_bld_intr.h"
 #include "gallivm/lp_bld_flow.h"
 #include "gallivm/lp_bld_type.h"
@@ -454,6 +455,78 @@ emit_position_coef( struct gallivm_state *gallivm,
 }
 
 
+/**
+ * Applys cylindrical wrapping to vertex attributes if enabled.
+ * Input coordinates must be in [0, 1] range, otherwise results are undefined.
+ *
+ * @param cyl_wrap  TGSI_CYLINDRICAL_WRAP_x flags
+ */
+static void
+emit_apply_cyl_wrap(struct gallivm_state *gallivm,
+                    struct lp_setup_args *args,
+                    uint cyl_wrap)
+{
+   LLVMBuilderRef builder = gallivm->builder;
+   struct lp_type type = lp_float32_vec4_type();
+   LLVMTypeRef float_vec_type = lp_build_vec_type(gallivm, type);
+   LLVMValueRef pos_half;
+   LLVMValueRef neg_half;
+   LLVMValueRef cyl_mask;
+   LLVMValueRef offset;
+   LLVMValueRef delta;
+   LLVMValueRef one;
+
+   if (!cyl_wrap)
+      return;
+
+   /* Constants */
+   pos_half = lp_build_const_vec(gallivm, type, +0.5f);
+   neg_half = lp_build_const_vec(gallivm, type, -0.5f);
+   cyl_mask = lp_build_const_mask_aos(gallivm, type, cyl_wrap);
+
+   one = lp_build_const_vec(gallivm, type, 1.0f);
+   one = LLVMBuildBitCast(builder, one, lp_build_int_vec_type(gallivm, type), "");
+   one = LLVMBuildAnd(builder, one, cyl_mask, "");
+
+   /* Edge v0 -> v1 */
+   delta = LLVMBuildFSub(builder, args->v1a, args->v0a, "");
+
+   offset    = lp_build_compare(gallivm, type, PIPE_FUNC_GREATER, delta, pos_half);
+   offset    = LLVMBuildAnd(builder, offset, one, "");
+   offset    = LLVMBuildBitCast(builder, offset, float_vec_type, "");
+   args->v0a = LLVMBuildFAdd(builder, args->v0a, offset, "");
+
+   offset    = lp_build_compare(gallivm, type, PIPE_FUNC_LESS, delta, neg_half);
+   offset    = LLVMBuildAnd(builder, offset, one, "");
+   offset    = LLVMBuildBitCast(builder, offset, float_vec_type, "");
+   args->v1a = LLVMBuildFAdd(builder, args->v1a, offset, "");
+
+   /* Edge v1 -> v2 */
+   delta = LLVMBuildFSub(builder, args->v2a, args->v1a, "");
+
+   offset    = lp_build_compare(gallivm, type, PIPE_FUNC_GREATER, delta, pos_half);
+   offset    = LLVMBuildAnd(builder, offset, one, "");
+   offset    = LLVMBuildBitCast(builder, offset, float_vec_type, "");
+   args->v1a = LLVMBuildFAdd(builder, args->v1a, offset, "");
+
+   offset    = lp_build_compare(gallivm, type, PIPE_FUNC_LESS, delta, neg_half);
+   offset    = LLVMBuildAnd(builder, offset, one, "");
+   offset    = LLVMBuildBitCast(builder, offset, float_vec_type, "");
+   args->v2a = LLVMBuildFAdd(builder, args->v2a, offset, "");
+
+   /* Edge v2 -> v0 */
+   delta = LLVMBuildFSub(builder, args->v0a, args->v2a, "");
+
+   offset    = lp_build_compare(gallivm, type, PIPE_FUNC_GREATER, delta, pos_half);
+   offset    = LLVMBuildAnd(builder, offset, one, "");
+   offset    = LLVMBuildBitCast(builder, offset, float_vec_type, "");
+   args->v2a = LLVMBuildFAdd(builder, args->v2a, offset, "");
+
+   offset    = lp_build_compare(gallivm, type, PIPE_FUNC_LESS, delta, neg_half);
+   offset    = LLVMBuildAnd(builder, offset, one, "");
+   offset    = LLVMBuildBitCast(builder, offset, float_vec_type, "");
+   args->v0a = LLVMBuildFAdd(builder, args->v0a, offset, "");
+}
 
 
 /**
@@ -491,10 +564,12 @@ emit_tri_coef( struct gallivm_state *gallivm,
         break;
 
       case LP_INTERP_LINEAR:
+        emit_apply_cyl_wrap(gallivm, args, key->inputs[slot].cyl_wrap);
         emit_linear_coef(gallivm, args, slot+1);
          break;
 
       case LP_INTERP_PERSPECTIVE:
+        emit_apply_cyl_wrap(gallivm, args, key->inputs[slot].cyl_wrap);
         emit_perspective_coef(gallivm, args, slot+1);
          break;
 
@@ -763,7 +838,7 @@ lp_make_setup_variant_key(struct llvmpipe_context *lp,
    struct lp_fragment_shader *fs = lp->fs;
    unsigned i;
 
-   assert(sizeof key->inputs[0] == sizeof(ushort));
+   assert(sizeof key->inputs[0] == sizeof(uint));
    
    key->num_inputs = fs->info.base.num_inputs;
    key->flatshade_first = lp->rasterizer->flatshade_first;