diff options
author | Dave Airlie <[email protected]> | 2015-06-27 14:21:54 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2015-07-01 12:53:43 +1000 |
commit | e35c5717837d9ac6d9722b011852bdf187f29776 (patch) | |
tree | a4bc9a2d182d8b8e8e985385136a68bc98a9b2eb /src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c | |
parent | 5ccd61217d873567b8d9a7a0fa8f678522ec78cb (diff) |
gallivm: add fp64 support. (v2.1)
This adds support for ARB_gpu_shader_fp64 and ARB_vertex_attrib_64bit to
llvmpipe.
Two things that don't mix well are SoA and doubles, see
emit_fetch_double, and emit_store_double_chan in this.
I've also had to split emit_data.chan, to add src_chan,
which can be different for doubles.
It handles indirect double fetches from temps, inputs, constants
and immediates. It doesn't handle double stores to indirects,
however it appears the mesa/st doesn't currently emit these,
it always does UARL/MOV combos, which will work fine.
tested with piglit, no regressions, all the fp64 tests seem to pass.
v2:
switch to using shuffles for fetch/store (Roland)
assert on indirect double stores - mesa/st never emits these (it uses MOV)
fix indirect temp/input/constant/immediates (Roland)
typos/formatting fixes (Roland)
v2.1:
cleanup some long lines, emit_store_double_chan cleanups.
Reviewed-by: Roland Scheidegger <[email protected]>
Signed-off-by: Dave Airlie <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c')
-rw-r--r-- | src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c index 9cb42b237b7..1f2af85c92b 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_tgsi_action.c @@ -894,6 +894,125 @@ const struct lp_build_tgsi_action xpd_action = { xpd_emit /* emit */ }; +/* TGSI_OPCODE_D2F */ +static void +d2f_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = + LLVMBuildFPTrunc(bld_base->base.gallivm->builder, + emit_data->args[0], + bld_base->base.vec_type, ""); +} + +/* TGSI_OPCODE_D2I */ +static void +d2i_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = + LLVMBuildFPToSI(bld_base->base.gallivm->builder, + emit_data->args[0], + bld_base->base.int_vec_type, ""); +} + +/* TGSI_OPCODE_D2U */ +static void +d2u_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = + LLVMBuildFPToUI(bld_base->base.gallivm->builder, + emit_data->args[0], + bld_base->base.int_vec_type, ""); +} + +/* TGSI_OPCODE_F2D */ +static void +f2d_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = + LLVMBuildFPExt(bld_base->base.gallivm->builder, + emit_data->args[0], + bld_base->dbl_bld.vec_type, ""); +} + +/* TGSI_OPCODE_U2D */ +static void +u2d_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = + LLVMBuildUIToFP(bld_base->base.gallivm->builder, + emit_data->args[0], + bld_base->dbl_bld.vec_type, ""); +} + +/* TGSI_OPCODE_I2D */ +static void +i2d_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = + LLVMBuildSIToFP(bld_base->base.gallivm->builder, + emit_data->args[0], + bld_base->dbl_bld.vec_type, ""); +} + +/* TGSI_OPCODE_DMAD */ +static void +dmad_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + LLVMValueRef tmp; + tmp = lp_build_emit_llvm_binary(bld_base, TGSI_OPCODE_DMUL, + emit_data->args[0], + emit_data->args[1]); + emit_data->output[emit_data->chan] = lp_build_emit_llvm_binary(bld_base, + TGSI_OPCODE_DADD, tmp, emit_data->args[2]); +} + +/*.TGSI_OPCODE_DRCP.*/ +static void drcp_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + LLVMValueRef one; + one = lp_build_const_vec(bld_base->dbl_bld.gallivm, bld_base->dbl_bld.type, 1.0f); + emit_data->output[emit_data->chan] = LLVMBuildFDiv( + bld_base->base.gallivm->builder, + one, emit_data->args[0], ""); +} + +/* TGSI_OPCODE_DFRAC */ +static void dfrac_emit( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + LLVMValueRef tmp; + tmp = lp_build_floor(&bld_base->dbl_bld, + emit_data->args[0]); + emit_data->output[emit_data->chan] = LLVMBuildFSub(bld_base->base.gallivm->builder, + emit_data->args[0], tmp, ""); +} + void lp_set_default_actions(struct lp_build_tgsi_context * bld_base) { @@ -948,6 +1067,25 @@ lp_set_default_actions(struct lp_build_tgsi_context * bld_base) bld_base->op_actions[TGSI_OPCODE_MAX].emit = fmax_emit; bld_base->op_actions[TGSI_OPCODE_MIN].emit = fmin_emit; + + bld_base->op_actions[TGSI_OPCODE_DADD].emit = add_emit; + bld_base->op_actions[TGSI_OPCODE_DMAX].emit = fmax_emit; + bld_base->op_actions[TGSI_OPCODE_DMIN].emit = fmin_emit; + bld_base->op_actions[TGSI_OPCODE_DMUL].emit = mul_emit; + + bld_base->op_actions[TGSI_OPCODE_D2F].emit = d2f_emit; + bld_base->op_actions[TGSI_OPCODE_D2I].emit = d2i_emit; + bld_base->op_actions[TGSI_OPCODE_D2U].emit = d2u_emit; + + bld_base->op_actions[TGSI_OPCODE_F2D].emit = f2d_emit; + bld_base->op_actions[TGSI_OPCODE_I2D].emit = i2d_emit; + bld_base->op_actions[TGSI_OPCODE_U2D].emit = u2d_emit; + + bld_base->op_actions[TGSI_OPCODE_DMAD].emit = dmad_emit; + + bld_base->op_actions[TGSI_OPCODE_DRCP].emit = drcp_emit; + bld_base->op_actions[TGSI_OPCODE_DFRAC].emit = dfrac_emit; + } /* CPU Only default actions */ @@ -1792,6 +1930,104 @@ xor_emit_cpu( emit_data->args[1]); } +/* TGSI_OPCODE_DABS (CPU Only) */ +static void +dabs_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = lp_build_abs(&bld_base->dbl_bld, + emit_data->args[0]); +} + +/* TGSI_OPCODE_DNEG (CPU Only) */ +static void +dneg_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = lp_build_sub(&bld_base->dbl_bld, + bld_base->dbl_bld.zero, + emit_data->args[0]); +} + +/* TGSI_OPCODE_DSET Helper (CPU Only) */ +static void +dset_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data, + unsigned pipe_func) +{ + LLVMValueRef cond = lp_build_cmp(&bld_base->dbl_bld, pipe_func, + emit_data->args[0], emit_data->args[1]); + emit_data->output[emit_data->chan] = cond; +} + +/* TGSI_OPCODE_DSEQ (CPU Only) */ +static void +dseq_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + dset_emit_cpu(action, bld_base, emit_data, PIPE_FUNC_EQUAL); +} + +/* TGSI_OPCODE_DSGE (CPU Only) */ +static void +dsge_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + dset_emit_cpu(action, bld_base, emit_data, PIPE_FUNC_GEQUAL); +} + +/* TGSI_OPCODE_DSLT (CPU Only) */ +static void +dslt_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + dset_emit_cpu(action, bld_base, emit_data, PIPE_FUNC_LESS); +} + +/* TGSI_OPCODE_DSNE (CPU Only) */ +static void +dsne_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + dset_emit_cpu(action, bld_base, emit_data, PIPE_FUNC_NOTEQUAL); +} + +/* Double Reciprocal squareroot (CPU Only) */ +static void +drecip_sqrt_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = lp_build_rsqrt(&bld_base->dbl_bld, + emit_data->args[0]); +} + +/* Double Squareroot (CPU Only) */ +static void +dsqrt_emit_cpu( + const struct lp_build_tgsi_action * action, + struct lp_build_tgsi_context * bld_base, + struct lp_build_emit_data * emit_data) +{ + emit_data->output[emit_data->chan] = lp_build_sqrt(&bld_base->dbl_bld, + emit_data->args[0]); +} + void lp_set_default_actions_cpu( struct lp_build_tgsi_context * bld_base) @@ -1864,4 +2100,14 @@ lp_set_default_actions_cpu( bld_base->op_actions[TGSI_OPCODE_XOR].emit = xor_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DABS].emit = dabs_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DNEG].emit = dneg_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DSEQ].emit = dseq_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DSGE].emit = dsge_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DSLT].emit = dslt_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DSNE].emit = dsne_emit_cpu; + + bld_base->op_actions[TGSI_OPCODE_DRSQ].emit = drecip_sqrt_emit_cpu; + bld_base->op_actions[TGSI_OPCODE_DSQRT].emit = dsqrt_emit_cpu; + } |