From f34e2f484bb73bba79a5b3fa7cff2e79bc7f0cf9 Mon Sep 17 00:00:00 2001 From: James Benton Date: Mon, 18 Jun 2012 17:31:39 +0100 Subject: [PATCH] llvmpipe: Implement cylindrical wrapping. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested against mesa demos cylwrap and dx9 DCT address.exe which now passes 100%. Signed-off-by: José Fonseca --- src/gallium/drivers/llvmpipe/lp_bld_interp.h | 8 +- src/gallium/drivers/llvmpipe/lp_state_fs.c | 1 + src/gallium/drivers/llvmpipe/lp_state_setup.c | 77 ++++++++++++++++++- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/gallium/drivers/llvmpipe/lp_bld_interp.h b/src/gallium/drivers/llvmpipe/lp_bld_interp.h index b0cbd9bdaec..6970a9b8c2c 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_interp.h +++ b/src/gallium/drivers/llvmpipe/lp_bld_interp.h @@ -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; }; diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 0bdc17fb3e1..7dd49691051 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -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: diff --git a/src/gallium/drivers/llvmpipe/lp_state_setup.c b/src/gallium/drivers/llvmpipe/lp_state_setup.c index 212bc1b9d05..299c1ef85dc 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_state_setup.c @@ -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;